Situacija dažnai sutinkama kasdieniniame darbe. Turim select’ą su daug where sąlygų. Vieną kartą select’ą tenka įvykdyti su vienomis sąlygomis, antrą kartą su kitomis, trečią – su visomis išskyrus vieną ir pan. Jeigu select’as trumpas, bėdos nėra: užkomentuojam nereikalingas eilutes ir tiek. Jeigu select’as yra labai ilgas, su daug join’ų, union’ų ir daug daug kintančių sąlygų, problema pasidaro gan rimta. Galima lengvai susipainioti ar kažką praleisti. Taip pat toks „užkomentavimo” metodas nelabai tinka automatiniam ataskaitų generavimui. Na bet pasirodo yra gan paprastas ir patogus where sąlygų įjungimo/išjungimo būdas.
Apie viską iš pradžių. Tarkim, turim lentelę t, kurioje yra saugomi įrašai susidedantys iš id, date ir type stulpelių:
ID DT TYPE -- ------------------- ----- 1 2014-08-01 00:00:00 A 2 2014-08-01 01:00:00 B 3 2014-08-01 02:00:00 A 4 2014-08-01 03:00:00 B 5 2014-08-01 04:00:00 A 6 2014-08-01 05:00:00 B 7 2014-08-01 06:00:00 A 8 2014-08-01 07:00:00 B
Pasibandymui (pav. ant sqlfiddle.com) tokią lentelę galit pasigaminti taip:
create table t (id number, DT date, type VARCHAR2(5 CHAR)); insert into t (id, DT, type) SELECT rownum as id ,TO_DATE('2014-08-01', 'yyyy-mm-dd') + (rownum-1)*(1/24) AS DT ,case when mod(rownum,2) = 1 then 'A' else 'B' end as type FROM dual CONNECT BY LEVEL <= (TO_DATE('2014-08-05 00:00:00', 'yyyy-mm-dd HH24:MI:SS') - TO_DATE('2014-08-01 00:00:00', 'yyyy-mm-dd HH24:MI:SS'))*2 order by 1;
Įsivaizduokim situaciją, kad dažnai reikia paselectinti tam tikro laiko visų arba tik ‘A’ tipo duomenis. Kitaip sakant, dažnai tenka vykdyti arba vieną arba kitą selectą:
select * from t where DT > to_date('2014-08-01 02:00:00', 'yyyy-mm-dd HH24:MI:SS') order by ID
select * from t where DT > to_date('2014-08-01 02:00:00', 'yyyy-mm-dd HH24:MI:SS') and type = 'A' order by ID
Jeigu select’as trumpas, bėdos nėra. Jeigu ilgas ir sudėtingas – atsiranda šiokių tokių problemų. Gerai, kad protingi žmonės sugalvojo genialiai paprastą sprendimą, išnaudojantį loginį ARBA (OR). Naudojantys SQL Developer, gali šį metodą išsibandyti taip:
select * from t where DT > to_date('2014-08-01 02:00:00', 'yyyy-mm-dd HH24:MI:SS') and (1=:ignore_type OR type = 'A') order by ID
Čia, trečiąją kodo eilutę papildžiau išmone 1=:ignore_type. Kas čia per padaras, paklausit. O gi viskas labai paprasta. Šį daiktą reikia suprasti taip: jeigu parametrą ignore_type nustatysime lygų vienam, sąlygą type = ‘A’ bus ignoruojama. Jeigu nustatysime, kad ignore_type=0 į sąlygą type = ‘A’ bus atsižvelgta.
Kitaip sakant, parametro ignore_type reikšmę nustatę 1 arba 0 selecto sąlygą vienu ar kitu atveju pakeisime taip:
select * from t where DT > to_date('2014-08-01 02:00:00', 'yyyy-mm-dd HH24:MI:SS') and (1=1 OR type = 'A') order by ID
select * from t where DT > to_date('2014-08-01 02:00:00', 'yyyy-mm-dd HH24:MI:SS') and (1=0 OR type = 'A') order by ID
Nuo seno SQL kalboje išraiška 1=1 yra tolygi TRUE, o 1=0 yra lygi FALSE. O ką daro operatorius OR? Jis pasirenka arba vieną sąlygą arba kitą. Jeigu pirma sąlyga yra teisinga, antroji yra tiesiog ignoruojama. T. y. viršuje aprašyti selectai pavirsta tokiais:
select * from t where DT > to_date('2014-08-01 02:00:00', 'yyyy-mm-dd HH24:MI:SS') and (1=1) order by ID
select * from t where DT > to_date('2014-08-01 02:00:00', 'yyyy-mm-dd HH24:MI:SS') and (type = 'A') order by ID
Ir tai veikia! Tiesiog mind blow: