9.18. УÑловнÑе вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ #
Ð ÑÑом Ñазделе опиÑÐ°Ð½Ñ SQL-ÑовмеÑÑимÑе ÑÑловнÑе вÑÑажениÑ, коÑоÑÑе поддеÑживаÑÑÑÑ Ð² Postgres Pro.
ÐодÑказка
ÐÑли возможноÑÑей ÑÑÐ¸Ñ ÑÑловнÑÑ Ð²ÑÑажений оказÑваеÑÑÑ Ð½ÐµÐ´Ð¾ÑÑаÑоÑно, веÑоÑÑно, Ð¸Ð¼ÐµÐµÑ ÑмÑÑл пеÑейÑи к напиÑÐ°Ð½Ð¸Ñ ÑеÑвеÑнÑÑ ÑÑнкÑий на более моÑном ÑзÑке пÑогÑаммиÑованиÑ.
ÐÑимеÑание
ХоÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑии COALESCE, GREATEST и LEAST ÑинÑакÑиÑеÑки поÑ
ожи на ÑÑнкÑии, они не ÑвлÑÑÑÑÑ Ð¾Ð±ÑÑнÑми ÑÑнкÑиÑми, и поÑÑÐ¾Ð¼Ñ Ð¸Ð¼ нелÑÐ·Ñ Ð¿ÐµÑедаÑÑ Ð² аÑгÑменÑаÑ
Ñвно опиÑаннÑй маÑÑив VARIADIC.
9.18.1. CASE #
ÐÑÑажение CASE в SQL пÑедÑÑавлÑÐµÑ Ñобой обÑее ÑÑловное вÑÑажение, напоминаÑÑее опеÑаÑоÑÑ if/else в дÑÑгиÑ
ÑзÑкаÑ
пÑогÑаммиÑованиÑ:
CASE WHENÑÑловиеTHENÑезÑлÑÑаÑ[WHEN ...] [ELSEÑезÑлÑÑаÑ] END
ÐÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ CASE можно иÑполÑзоваÑÑ Ð²ÐµÐ·Ð´Ðµ, где допÑÑкаÑÑÑÑ Ð²ÑÑажениÑ. Ðаждое ÑÑловие в нÑм пÑедÑÑавлÑÐµÑ Ñобой вÑÑажение, возвÑаÑаÑÑее ÑезÑлÑÑÐ°Ñ Ñипа boolean. ÐÑли ÑезÑлÑÑаÑом вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð¾ÐºÐ°Ð·ÑваеÑÑÑ true, знаÑением вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ CASE ÑÑановиÑÑÑ ÑезÑлÑÑаÑ, ÑледÑÑÑий за ÑÑловием, а оÑÑалÑÐ½Ð°Ñ ÑаÑÑÑ Ð²ÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ CASE не вÑÑиÑлÑеÑÑÑ. ÐÑли же ÑÑловие не вÑполнÑеÑÑÑ, за ним Ñаким же обÑазом пÑовеÑÑÑÑÑÑ Ð²Ñе поÑледÑÑÑие пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ WHEN. ÐÑли не вÑполнÑеÑÑÑ Ð½Ð¸ одно из ÑÑловий WHEN, знаÑением CASE ÑÑановиÑÑÑ ÑезÑлÑÑаÑ, запиÑаннÑй в пÑедложении ELSE. ÐÑли пÑи ÑÑом пÑедложение ELSE оÑÑÑÑÑÑвÑеÑ, ÑезÑлÑÑаÑом вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð±ÑÐ´ÐµÑ NULL.
ÐÑимеÑ:
SELECT * FROM test;
a
---
1
2
3
SELECT a,
CASE WHEN a=1 THEN 'one'
WHEN a=2 THEN 'two'
ELSE 'other'
END
FROM test;
a | case
---+-------
1 | one
2 | two
3 | other
Ð¢Ð¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ
вÑеÑ
вÑÑажений ÑезÑлÑÑаÑов Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿ÑиводиÑÑÑÑ Ðº Ð¾Ð´Ð½Ð¾Ð¼Ñ Ð²ÑÑ
Ð¾Ð´Ð½Ð¾Ð¼Ñ ÑипÑ. ÐодÑобнее ÑÑо опиÑано в Разделе 10.5.
СÑÑеÑÑвÑÐµÑ Ñакже «пÑоÑÑаÑ» ÑоÑма вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ CASE, ÑазновидноÑÑÑ Ð²ÑÑепÑиведÑнной обÑей ÑоÑмÑ:
CASEвÑÑажениеWHENзнаÑениеTHENÑезÑлÑÑаÑ[WHEN ...] [ELSEÑезÑлÑÑаÑ] END
Ð Ñакой ÑоÑме ÑнаÑала вÑÑиÑлÑеÑÑÑ Ð¿ÐµÑвое вÑÑажение, а заÑем его ÑезÑлÑÑÐ°Ñ ÑÑавниваеÑÑÑ Ñ Ð²ÑÑажениÑми знаÑений в пÑедложениÑÑ
WHEN, пока не бÑÐ´ÐµÑ Ð½Ð°Ð¹Ð´ÐµÐ½Ð¾ Ñавное емÑ. ÐÑли Ñакого знаÑÐµÐ½Ð¸Ñ Ð½Ðµ наÑ
одиÑÑÑ, возвÑаÑаеÑÑÑ ÑезÑлÑÑÐ°Ñ Ð¿ÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ELSE (или NULL). ÐÑа ÑоÑма болÑÑе поÑ
ожа на опеÑаÑÐ¾Ñ switch, ÑÑÑеÑÑвÑÑÑий в ÑзÑке C.
ÐоказаннÑй Ñанее пÑÐ¸Ð¼ÐµÑ Ð¼Ð¾Ð¶Ð½Ð¾ запиÑаÑÑ Ð¿Ð¾-дÑÑгомÑ, иÑполÑзÑÑ Ð¿ÑоÑÑÑÑ ÑоÑÐ¼Ñ CASE:
SELECT a,
CASE a WHEN 1 THEN 'one'
WHEN 2 THEN 'two'
ELSE 'other'
END
FROM test;
a | case
---+-------
1 | one
2 | two
3 | other
РвÑÑажении CASE вÑÑиÑлÑÑÑÑÑ ÑолÑко Ñе подвÑÑажениÑ, коÑоÑÑе необÑ
Ð¾Ð´Ð¸Ð¼Ñ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ ÑезÑлÑÑаÑа. ÐапÑимеÑ, Ñак можно избежаÑÑ Ð¾Ñибки Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð½Ð° нолÑ:
SELECT ... WHERE CASE WHEN x <> 0 THEN y/x > 1.5 ELSE false END;
ÐÑимеÑание
Ðак бÑло опиÑано в ÐодÑазделе 4.2.14, вÑÑ Ð¶Ðµ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ ÑиÑÑаÑии, когда подвÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð²ÑÑиÑлÑÑÑÑÑ Ð½Ð° ÑазнÑÑ
ÑÑапаÑ
, Ñак ÑÑо железной гаÑанÑии, ÑÑо в «CASE вÑÑиÑлÑÑÑÑÑ ÑолÑко необÑ
одимÑе подвÑÑажениÑ», в пÑинÑипе неÑ. ÐапÑимеÑ, конÑÑанÑное подвÑÑажение 1/0 обÑÑно вÑзÑÐ²Ð°ÐµÑ Ð¾ÑÐ¸Ð±ÐºÑ Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð½Ð° Ð½Ð¾Ð»Ñ Ð½Ð° ÑÑапе планиÑованиÑ, Ñ
оÑÑ ÑÑа веÑÐ²Ñ CASE Ð¼Ð¾Ð¶ÐµÑ Ð²Ð¾Ð²Ñе не вÑÑиÑлÑÑÑÑÑ Ð²Ð¾ вÑÐµÐ¼Ñ Ð²ÑполнениÑ.
9.18.2. COALESCE #
COALESCE(знаÑение[, ...])
ФÑнкÑÐ¸Ñ COALESCE возвÑаÑÐ°ÐµÑ Ð¿ÐµÑвÑй попавÑийÑÑ Ð°ÑгÑменÑ, оÑлиÑнÑй Ð¾Ñ NULL. ÐÑли же вÑе аÑгÑменÑÑ ÑÐ°Ð²Ð½Ñ NULL, ÑезÑлÑÑаÑом Ñоже бÑÐ´ÐµÑ NULL. ÐÑо ÑаÑÑо иÑполÑзÑеÑÑÑ Ð¿Ñи оÑобÑажении даннÑÑ
Ð´Ð»Ñ Ð¿Ð¾Ð´ÑÑановки некоÑоÑого знаÑÐµÐ½Ð¸Ñ Ð¿Ð¾ ÑмолÑÐ°Ð½Ð¸Ñ Ð²Ð¼ÐµÑÑо знаÑений NULL:
SELECT COALESCE(description, short_description, '(none)') ...
ÐÑÐ¾Ñ Ð·Ð°Ð¿ÑÐ¾Ñ Ð²ÐµÑнÑÑ Ð·Ð½Ð°Ñение description, еÑли оно не Ñавно NULL, либо short_description, еÑли оно не NULL, и ÑÑÑÐ¾ÐºÑ (none), еÑли оба ÑÑи знаÑÐµÐ½Ð¸Ñ ÑÐ°Ð²Ð½Ñ NULL.
ÐÑгÑменÑÑ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð¿ÑиводимÑми к Ð¾Ð´Ð½Ð¾Ð¼Ñ Ð¾Ð±ÑÐµÐ¼Ñ ÑипÑ, коÑоÑÑй и бÑÐ´ÐµÑ Ñипом ÑезÑлÑÑаÑа (подÑобнее об ÑÑом говоÑиÑÑÑ Ð² Разделе 10.5).
Ðак и вÑÑажение CASE, COALESCE вÑÑиÑлÑÐµÑ ÑолÑко Ñе аÑгÑменÑÑ, коÑоÑÑе необÑ
Ð¾Ð´Ð¸Ð¼Ñ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ ÑезÑлÑÑаÑа; Ñо еÑÑÑ, аÑгÑменÑÑ Ð¿Ñавее пеÑвого оÑлиÑного Ð¾Ñ NULL аÑгÑменÑа не вÑÑиÑлÑÑÑÑÑ. ÐÑа ÑÑнкÑÐ¸Ñ ÑооÑвеÑÑÑвÑÐµÑ ÑÑандаÑÑÑ SQL, а в некоÑоÑÑÑ
дÑÑгиÑ
СУÐÐ ÐµÑ Ð°Ð½Ð°Ð»Ð¾Ð³Ð¸ назÑваÑÑÑÑ NVL и IFNULL.
9.18.3. NULLIF #
NULLIF(знаÑение1,знаÑение2)
ФÑнкÑÐ¸Ñ NULLIF вÑдаÑÑ Ð·Ð½Ð°Ñение NULL, еÑли знаÑение1 Ñавно знаÑение2; в пÑоÑивном ÑлÑÑае она возвÑаÑÐ°ÐµÑ Ð·Ð½Ð°Ñение1. ÐÑо Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾ Ð´Ð»Ñ ÑеализаÑии обÑаÑной опеÑаÑии к COALESCE. Ð ÑаÑÑноÑÑи, Ð´Ð»Ñ Ð¿ÑимеÑа, показанного вÑÑе:
SELECT NULLIF(value, '(none)') ...
Рданном пÑимеÑе еÑли value Ñавно (none), вÑдаÑÑÑÑ null, а инаÑе возвÑаÑаеÑÑÑ Ð·Ð½Ð°Ñение value.
Ðва ÐµÑ Ð°ÑгÑменÑа Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ ÑÑавнимÑÑ
Ñипов. ÐÑли говоÑиÑÑ ÑоÑнее, они ÑÑавниваÑÑÑÑ ÑоÑно Ñак же, как ÑÑавнивалиÑÑ Ð±Ñ Ð² запиÑи , Ñак ÑÑо Ð´Ð»Ñ ÑÑиÑ
Ñипов должен ÑÑÑеÑÑвоваÑÑ Ð¿Ð¾Ð´Ñ
одÑÑий опеÑаÑÐ¾Ñ Ð·Ð½Ð°Ñение1 = знаÑение2=.
РезÑлÑÑÐ°Ñ Ð±ÑÐ´ÐµÑ Ð¸Ð¼ÐµÑÑ ÑÐ¾Ñ Ð¶Ðµ Ñип, ÑÑо и пеÑвÑй аÑгÑменÑ, но еÑÑÑ Ð¾Ð´Ð½Ð° ÑонкоÑÑÑ. ÐÑа ÑÑнкÑÐ¸Ñ ÑакÑиÑеÑки возвÑаÑÐ°ÐµÑ Ð¿ÐµÑвÑй аÑгÑÐ¼ÐµÐ½Ñ Ð¿Ð¾Ð´ÑазÑмеваемого опеÑаÑоÑа =, коÑоÑÑй в некоÑоÑÑÑ
ÑлÑÑаÑÑ
пÑеобÑазÑеÑÑÑ Ðº ÑÐ¸Ð¿Ñ Ð²ÑоÑого аÑгÑменÑа. ÐапÑимеÑ, NULLIF(1, 2.2) возвÑаÑÐ°ÐµÑ numeric, Ñак как опеÑаÑÐ¾Ñ integer = numeric не ÑÑÑеÑÑвÑеÑ, ÑÑÑеÑÑвÑÐµÑ ÑолÑко опеÑаÑÐ¾Ñ numeric = numeric.
9.18.4. GREATEST и LEAST #
GREATEST(знаÑение[, ...])
LEAST(знаÑение[, ...])
ФÑнкÑии GREATEST и LEAST вÑбиÑаÑÑ Ð½Ð°Ð¸Ð±Ð¾Ð»ÑÑее или наименÑÑее знаÑение из ÑпиÑка вÑÑажений. ÐÑе ÑÑи вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿ÑиводиÑÑÑÑ Ðº обÑÐµÐ¼Ñ ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ
, коÑоÑÑй ÑÑÐ°Ð½ÐµÑ Ñипом ÑезÑлÑÑаÑа (подÑобнее об ÑÑом в Разделе 10.5).
ÐнаÑÐµÐ½Ð¸Ñ NULL в ÑÑом ÑпиÑке игноÑиÑÑÑÑÑÑ, Ñак ÑÑо ÑезÑлÑÑÐ°Ñ Ð²ÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð±ÑÐ´ÐµÑ Ñавен NULL, ÑолÑко еÑли вÑе его аÑгÑменÑÑ ÑÐ°Ð²Ð½Ñ NULL. (ÐÑо оÑклонение Ð¾Ñ ÑÑандаÑÑа SQL. СоглаÑно ÑÑандаÑÑÑ, возвÑаÑаеÑÑÑ Ð·Ð½Ð°Ñение NULL, еÑли какой-либо аÑгÑÐ¼ÐµÐ½Ñ Ñавен NULL. ÐодобнÑм обÑазом ведÑÑ ÑÐµÐ±Ñ Ð¸ некоÑоÑÑе дÑÑгие Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ .)