Наишао сам на занимљив проблем, тотално нестандардан и прилично тежак на прву лопту. Наиме, замислите табелу са подацима, с тим да ти подаци у табели представљају податке који иду у круг, тј. циклично се на крај уређене табеле може надовезати почетак. Примери могу да буду празнични дани (који се понављају сваке године), некa Абелова група…Ево, направићу скрипт према примеру са празницима где имамо табелу:

CREATE TABLE PRAZNIK(
    id INTEGER NOT NULL,
    mesec INTEGER NOT NULL,
    dan INTEGER NOT NULL,
    CONSTRAINT PRAZNIK_PK PRIMARY KEY (ID)
);

Ово је табела у којој се чувају празници током године. Примети се лако да овде нема забележене године (јер нам практично и не треба). Проблем сада гласи: наћи следећи празник у односу на неки датум. Када се мало размисли, проблем није нимало наиван, јер морамо пазити да ако нема следећег празника до краја године, морамо узети први са почетка године. Има ту још патолошких случајева као што су када нема датума уопште или има само један датум (следећи датум је онда исти тај једини датум). Овде има још један малецки проблем – морамо да водимо рачуна о сортирању месеци и дана, али намерно сам и узео овај пример пошто је табела над којом сам ја ово радио имала сличне проблеме. За ово ћемо просто да нормализујемо дан и месец као:

(mesec, dan) == mesec*31+dan

добијајући на тај начин (нешто што личи на) редни број дана у години. So, without further adieu, ево га скрипт:

SELECT id, mesec, dan
FROM praznik
WHERE
mesec*31+dan=(
    SELECT min(mesec*31+dan)
    FROM praznik
    WHERE mesec*31+dan > &1
    OR
    0=(
        SELECT COUNT(*)
        FROM praznik
        WHERE mesec*31+dan > &1
    )
);

У горњем скрипту, &1 је датум у односу на који се жели следећи празник.
Као и увек, најбитнија је идеја, а она је овде да се врати минимални члан, али по два критеријума – цака је да су критеријуми (неуобичајено) повезани са логичким OR. Један критеријум (први) је ту да претражује све дане ПОСЛЕ &1, али, уколико нема ниједног, други је ту да се постара да се у том случају врату минимум целе табеле, тј. први празник у години. Ту је још и угњеждени упит (средњи) – он није потребан ако подаци могу да се сортирају без нормализације какву сам извео горе. Наравно, овај исти, мало модификовани упит може да се користи и за обрнуту ствар – налажење претходника (само се ‘>’ замени са ‘<’, и min() функција са max() функцијом):

SELECT id, mesec, dan
FROM praznik
WHERE
mesec*31+dan=(
    SELECT max(mesec*31+dan)
    FROM praznik
    WHERE mesec*31+dan < &1
    OR
    0=(
        SELECT COUNT(*)
        FROM praznik
        WHERE mesec*31+dan < &1
    )
);

Још једну ствар да напоменем – уместо:

0=(
    SELECT COUNT(*)
    FROM praznik
    WHERE mesec*31+dan < &1
)

могло је да иде и нека варијанта са NOT EXIST…
Ако неко зна још неки начин да се ово уради, нека јави…

,