Mamy tabelę z danymi, a jedna z cech danej (kolumna tabeli) jest wartością liczbową, którą chcemy przyporządkować do wybranego z ustalonych, nazwanych zakresów. W naszym przykładzie będzie to tabela temperatur.
| temperatura |
|---|
| -23,5 |
| -34,1 |
| -36,6 |
| -31,0 |
| -26,8 |
| 17,0 |
| -22,1 |
| -5,7 |
| -35,9 |
| -34,5 |
| 34,0 |
| 39,1 |
| 5,0 |
| 6,4 |
| -40,0 |
Przy małej ilości zakresów można to oczywiście osiągnąć poprzez konstrukcję CASE WHEN, np.:
SELECT t.temperatura,
CASE
WHEN t.temperatura>=-30 AND t.temperatura<-5 THEN 'mroźno'
WHEN t.temperatura>=-5 AND t.temperatura<0 THEN 'lekki mróz'
...
ELSE 'nie wiadomo' END
FROM temperatura AS t
Ale przy większej ilości zakresów będzie kłopot. Kłopot będzie również przy zmianie wartości lub opisów zakresów (ingerencja w zapytanie), albo przy wielojęzykowości serwisu gdzie opisy zakresów muszą być odpowiednie do języka.
Mróz, zimno, zimno...
Zakresy trzeba przenieść do tabeli i sprytnie połączyć je z tabelą wartości.
Niech nasza tabela zakresów wygląda tak:
| zakres | od | do |
|---|---|---|
| bardzo mroźno | -1000 | -30 |
| mroźno | -30 | -5 |
| lekki mróz | -5 | 0 |
| zimno | 0 | 5 |
| chłodno | 5 | 15 |
| letnio | 15 | 20 |
| ciepło | 20 | 30 |
| gorąco | 30 | 35 |
| upał | 35 | 1000 |
Wtedy nasze zapytanie (już bez CASE WHEN) będzie wyglądać tak:
SELECT t.temperatura,zt.zakres
FROM temperatura AS t, zakres_temperatury AS zt
WHERE t.temperatura>=zt.od AND t.temperatura<zt.do
Ciepło, ciepło, gorąco!
Połączyliśmy tabelę temperatur (WHERE możesz przenieść do warunku JOIN) poprzez dwa warunki nierówności operujące na wartości temperatury oraz wartości "od" i "do" zakresu.
Należy pamiętać o tym, że jeśli koniec jednego zakresu jest taki sam jak początek kolejnego (w tabeli zakresów), to należy użyć nierówności ostrej (jak w przykładzie). Jeśli natomiast wartość "do" zakresu jest mniejsza od wartości "do" kolejnego, to obydwie nierówności mogą być nieostre. Zasada dotyczy również wartości "od".
A jak właściwie wygląda wynik?
| temperatura | zakres |
|---|---|
| -23,5 | mroźno |
| -34,1 | bardzo mroźno |
| -36,6 | bardzo mroźno |
| -31,0 | bardzo mroźno |
| -26,8 | mroźno |
| 17,0 | letnio |
| -22,1 | mroźno |
| -5,7 | mroźno |
| -35,9 | bardzo mroźno |
| -34,5 | bardzo mroźno |
| 34,0 | gorąco |
| 39,1 | upał |
| 5,0 | chłodno |
| 6,4 | chłodno |
| -40,0 | bardzo mroźno |
Nic nie stoi na przeszkodzie, aby w zapytaniu użyć grupowania i funkcji agregującej, np. aby policzyć ile rekordów wpada do danego przedziału.
SELECT COUNT(t.temperatura) AS ilosc,zt.zakres
FROM temperatura AS t, zakres_temperatury AS zt
WHERE t.temperatura>=zt.od AND t.temperatura<zt.do
GROUP BY zt.id_zakres /* ewentualnie GROUP BY zt.zakres */
Wiesz już jak się dziś ubrać?