6. dubna 2012

Oracle, vyhodnocení časových podmínek

Dneska jsem řešil (pro mne) zajímavý případ - potřeboval jsem v Oracle databázi postavit dotaz s následujícími parametry:

  • zkontrolovat, že dva určité záznamy mají hodnotu DATE mezi 17:00 včerejšího dne a 7:00 dnešního dne,
  • jako výstup dotazu mít hodnotu true nebo false (v Oraclu 1 a 0).
Dejme tomu, že máme následující tabulku
CREATE TABLE result_log (
    code VARCHAR2(20),
    logged DATE
  );
do které vložíme  dva záznamy odpovídající našemu intervalu (17:00-7:00):
INSERT INTO result_log VALUES
  ('codeA', TRUNC(sysdate - 1) + 22 / 24);
INSERT INTO result_log VALUES
  ('codeB', TRUNC(sysdate) + 5 / 24);
Výsledek by měl vypadat nějak takto:
SELECT code, TO_CHAR(logged,
                     'YYYY-MM-DD HH24:MM:SS')
             AS logged
  FROM result_log;
CODE                 LOGGED
-------------------- -------------------
codeA                2012-04-05 22:04:00
codeB                2012-04-06 05:04:00
Požadované záznamy (codeA, codeB) vybereme následujícím dotazem a zároveň je ohodnotíme, že jsou/nejsou z daného časového intervalu (1 = jsou, 0 = nejsou):
SELECT
  CASE
    WHEN (logged BETWEEN
        (TRUNC(sysdate - 1) + 17 / 24) AND
        (TRUNC(sysdate) + 7 / 24))
    THEN 1
    ELSE 0
  END AS eveluation
FROM result_log
WHERE code IN ('codeA', 'codeB');
EVELUATION
----------
         1
         1
Jelikož nad výsledky potřebujeme v podstatě provést logickou konjunkci (AND) můžeme k tomuto účelu použít funkci DECODE. Výsledný dotaz pak vypadá následovně:
SELECT DECODE(SUM(eveluation), COUNT(*), 1, 0)
  AS evaluation
FROM
  (SELECT
    CASE
      WHEN (logged BETWEEN
        (TRUNC(sysdate - 1) + 17 / 24) AND
        (TRUNC(sysdate) + 7 / 24))
      THEN 1
      ELSE 0
    END AS eveluation
  FROM result_log
  WHERE code IN ('codeA', 'codeB')
  );
EVALUATION
----------
         1
Elegantní na tomto řešení je, že stačí pouze přidat do klauzule WHERE další kód (codeC) a vše ostatní bez problémů dál funguje.

Žádné komentáře:

Okomentovat