7.2. ТаблиÑнÑе вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ #
ТаблиÑное вÑÑажение вÑÑиÑлÑÐµÑ ÑаблиÑÑ. ÐÑо вÑÑажение ÑодеÑÐ¶Ð¸Ñ Ð¿Ñедложение FROM, за коÑоÑÑм могÑÑ ÑледоваÑÑ Ð¿ÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ WHERE, GROUP BY и HAVING. ТÑивиалÑнÑе ÑаблиÑнÑе вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð¿ÑоÑÑо ÑÑÑлаÑÑÑÑ Ð½Ð° ÑизиÑеÑкÑÑ ÑаблиÑÑ, ÐµÑ Ð½Ð°Ð·ÑваÑÑ Ñакже базовой, но в более ÑложнÑÑ
вÑÑажениÑÑ
Ñакие ÑаблиÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ пÑеобÑазовÑваÑÑ Ð¸ комбиниÑоваÑÑ ÑамÑми ÑазнÑми ÑпоÑобами.
ÐеобÑзаÑелÑнÑе пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ WHERE, GROUP BY и HAVING в ÑаблиÑном вÑÑажении опÑеделÑÑÑ Ð¿Ð¾ÑледоваÑелÑноÑÑÑ Ð¿ÑеобÑазований, оÑÑÑеÑÑвлÑемÑÑ
Ñ Ð´Ð°Ð½Ð½Ñми ÑаблиÑÑ, полÑÑенной в пÑедложении FROM. Ð ÑезÑлÑÑаÑе ÑÑиÑ
пÑеобÑазований обÑазÑеÑÑÑ Ð²Ð¸ÑÑÑалÑÐ½Ð°Ñ ÑаблиÑа, ÑÑÑоки коÑоÑой пеÑедаÑÑÑÑ ÑпиÑÐºÑ Ð²ÑбоÑки, вÑÑиÑлÑÑÑÐµÐ¼Ñ Ð²ÑÑ
однÑе ÑÑÑоки запÑоÑа.
7.2.1. ÐÑедложение FROM #
ÐÑедложение FROM обÑазÑÐµÑ ÑаблиÑÑ Ð¸Ð· одной или неÑколÑкиÑ
ÑÑÑлок на ÑаблиÑÑ, ÑазделÑннÑÑ
запÑÑÑми.
FROMÑаблиÑнаÑ_ÑÑÑлка[,ÑаблиÑнаÑ_ÑÑÑлка[, ...]]
ÐдеÑÑ ÑаблиÑной ÑÑÑлкой Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸Ð¼Ñ ÑаблиÑÑ (возможно, Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ ÑÑ
емÑ), пÑÐ¾Ð¸Ð·Ð²Ð¾Ð´Ð½Ð°Ñ ÑаблиÑа, напÑÐ¸Ð¼ÐµÑ Ð¿Ð¾Ð´Ð·Ð°Ð¿ÑоÑ, Ñоединение ÑÐ°Ð±Ð»Ð¸Ñ Ð¸Ð»Ð¸ ÑÐ»Ð¾Ð¶Ð½Ð°Ñ ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°ÑÐ¸Ñ ÑÑиÑ
ваÑианÑов. ÐÑли в пÑедложении FROM пеÑеÑиÑлÑÑÑÑÑ Ð½ÐµÑколÑко ÑÑÑлок, Ð´Ð»Ñ Ð½Ð¸Ñ
пÑименÑеÑÑÑ Ð¿ÐµÑекÑÑÑÑное Ñоединение (Ñо еÑÑÑ Ð´ÐµÐºÐ°ÑÑово пÑоизведение иÑ
ÑÑÑок; Ñм. ниже). СпиÑок FROM пÑеобÑазÑеÑÑÑ Ð² пÑомежÑÑоÑнÑÑ Ð²Ð¸ÑÑÑалÑнÑÑ ÑаблиÑÑ, коÑоÑÐ°Ñ Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑойÑи ÑеÑез пÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ WHERE, GROUP BY и HAVING, и в иÑоге опÑÐµÐ´ÐµÐ»Ð¸Ñ ÑезÑлÑÑÐ°Ñ ÑаблиÑного вÑÑажениÑ.
Ðогда в ÑаблиÑной ÑÑÑлке ÑказÑваеÑÑÑ ÑаблиÑа, ÑвлÑÑÑаÑÑÑ ÑодиÑелÑÑкой в иеÑаÑÑ
ии наÑледованиÑ, в ÑезÑлÑÑаÑе бÑдÑÑ Ð¿Ð¾Ð»ÑÑÐµÐ½Ñ ÑÑÑоки не ÑолÑко ÑÑой ÑаблиÑÑ, но и вÑеÑ
ÐµÑ Ð´Ð¾ÑеÑниÑ
ÑаблиÑ. ЧÑÐ¾Ð±Ñ Ð²ÑбÑаÑÑ ÑÑÑоки ÑолÑко одной ÑодиÑелÑÑкой ÑаблиÑÑ, пеÑед ÐµÑ Ð¸Ð¼ÐµÐ½ÐµÐ¼ нÑжно добавиÑÑ ÐºÐ»ÑÑевое Ñлово ONLY. УÑÑиÑе, ÑÑо пÑи ÑÑом бÑдÑÑ Ð¿Ð¾Ð»ÑÑÐµÐ½Ñ ÑолÑко ÑÑолбÑÑ Ñказанной ÑаблиÑÑ â дополниÑелÑнÑе ÑÑолбÑÑ Ð´Ð¾ÑеÑниÑ
ÑÐ°Ð±Ð»Ð¸Ñ Ð½Ðµ попадÑÑ Ð² ÑезÑлÑÑаÑ.
ÐÑли же Ð²Ñ Ð½Ðµ добавлÑеÑе ONLY пеÑед именем ÑаблиÑÑ, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе допиÑаÑÑ Ð¿Ð¾Ñле него *, Ñем ÑамÑм Ñказав, ÑÑо Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¾Ð±ÑабаÑÑваÑÑÑÑ Ð¸ вÑе доÑеÑние ÑаблиÑÑ. ÐÑакÑиÑеÑкиÑ
пÑиÑин иÑполÑзоваÑÑ ÑÑÐ¾Ñ ÑинÑакÑÐ¸Ñ Ð±Ð¾Ð»ÑÑе неÑ, Ñак как поиÑк в доÑеÑниÑ
ÑаблиÑаÑ
ÑепеÑÑ Ð¿ÑоизводиÑÑÑ Ð¿Ð¾ ÑмолÑаниÑ. Ðднако ÑÑа запиÑÑ Ð¿Ð¾Ð´Ð´ÐµÑживаеÑÑÑ Ð´Ð»Ñ ÑовмеÑÑимоÑÑи Ñо ÑÑаÑÑми веÑÑиÑми.
7.2.1.1. СоединÑннÑе ÑаблиÑÑ #
СоединÑÐ½Ð½Ð°Ñ ÑаблиÑа ÂÂÂÂÂÂâ ÑÑо ÑаблиÑа, полÑÑÐµÐ½Ð½Ð°Ñ Ð¸Ð· двÑÑ Ð´ÑÑÐ³Ð¸Ñ (ÑеалÑнÑÑ Ð¸Ð»Ð¸ пÑоизводнÑÑ Ð¾Ñ Ð½Ð¸Ñ ) ÑÐ°Ð±Ð»Ð¸Ñ Ð² ÑооÑвеÑÑÑвии Ñ Ð¿Ñавилами ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð½ÐºÑеÑного Ñипа. ÐбÑий ÑинÑакÑÐ¸Ñ Ð¾Ð¿Ð¸ÑÐ°Ð½Ð¸Ñ ÑоединÑнной ÑаблиÑÑ:
T1Ñип_ÑоединениÑT2[ÑÑловие_ÑоединениÑ]
Ð¡Ð¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ð»ÑбÑÑ
Ñипов могÑÑ Ð²ÐºÐ»Ð°Ð´ÑваÑÑÑÑ Ð´ÑÑг в дÑÑга или обÑединÑÑÑÑÑ: и T1, и T2 могÑÑ Ð±ÑÑÑ ÑезÑлÑÑаÑами ÑоединениÑ. ÐÐ»Ñ Ð¾Ð´Ð½Ð¾Ð·Ð½Ð°Ñного опÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ð¾ÑÑдка Ñоединений пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ JOIN можно заклÑÑаÑÑ Ð² Ñкобки. ÐÑли Ñкобки оÑÑÑÑÑÑвÑÑÑ, пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ JOIN обÑабаÑÑваÑÑÑÑ Ñлева напÑаво.
Ð¢Ð¸Ð¿Ñ Ñоединений
- ÐеÑекÑÑÑÑное Ñоединение
T1CROSS JOINT2СоединÑннÑÑ ÑаблиÑÑ Ð¾Ð±ÑазÑÑÑ Ð²Ñе возможнÑе ÑоÑеÑÐ°Ð½Ð¸Ñ ÑÑÑок из
T1иT2(Ñ. е. Ð¸Ñ Ð´ÐµÐºÐ°ÑÑово пÑоизведение), а Ð½Ð°Ð±Ð¾Ñ ÐµÑ ÑÑолбÑов обÑединÑÐµÑ Ð² Ñебе ÑÑолбÑÑT1Ñо ÑледÑÑÑими за ними ÑÑолбÑамиT2. ÐÑли ÑаблиÑÑ ÑодеÑÐ¶Ð°Ñ N и M ÑÑÑок, ÑоединÑÐ½Ð½Ð°Ñ ÑаблиÑа бÑÐ´ÐµÑ ÑодеÑжаÑÑ N * M ÑÑÑок.FROMÑавнознаÑноT1CROSS JOINT2FROM(Ñм. ниже). ÐÑа запиÑÑ Ñакже ÑавнознаÑнаT1INNER JOINT2ON TRUEFROM.T1,T2ÐÑимеÑание
ÐоÑледнÑÑ Ð·Ð°Ð¿Ð¸ÑÑ Ð½Ðµ полноÑÑÑÑ ÑквиваленÑна пеÑвÑм пÑи Ñказании более Ñем двÑÑ ÑаблиÑ, Ñак как
JOINÑвÑзÑÐ²Ð°ÐµÑ ÑаблиÑÑ ÑилÑнее, Ñем запÑÑаÑ. ÐапÑимеÑ,FROMне ÑавнознаÑноT1CROSS JOINT2INNER JOINT3ONÑÑловиеFROM, Ñак какT1,T2INNER JOINT3ONÑÑловиеÑÑÐ»Ð¾Ð²Ð¸ÐµÐ¼Ð¾Ð¶ÐµÑ ÑÑÑлаÑÑÑÑ Ð½Ð°T1в пеÑвом ÑлÑÑае, но не во вÑоÑом.- Ð¡Ð¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ ÑопоÑÑавлениÑми ÑÑÑок
T1{ [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOINT2ONлогиÑеÑкое_вÑÑажениеT1{ [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOINT2USING (ÑпиÑок ÑÑолбÑов ÑоединениÑ)T1NATURAL { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOINT2Слова
INNERиOUTERнеобÑзаÑелÑÐ½Ñ Ð²Ð¾ вÑÐµÑ ÑоÑÐ¼Ð°Ñ . Ðо ÑмолÑÐ°Ð½Ð¸Ñ Ð¿Ð¾Ð´ÑазÑмеваеÑÑÑINNER(внÑÑÑеннее Ñоединение), а пÑи ÑказанииLEFT,RIGHTиFULLâ внеÑнее Ñоединение.УÑловие ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ ÑказÑваеÑÑÑ Ð² пÑедложении
ONилиUSING, либо неÑвно задаÑÑÑÑ ÐºÐ»ÑÑевÑм ÑловомNATURAL. ÐÑо ÑÑловие опÑеделÑеÑ, какие ÑÑÑоки двÑÑ Ð¸ÑÑ Ð¾Ð´Ð½ÑÑ ÑÐ°Ð±Ð»Ð¸Ñ ÑÑиÑаÑÑÑÑ Â«ÑооÑвеÑÑÑвÑÑÑими» дÑÑг дÑÑÐ³Ñ (ÑÑо подÑобно ÑаÑÑмаÑÑиваеÑÑÑ Ð½Ð¸Ð¶Ðµ).ÐозможнÑе ÑÐ¸Ð¿Ñ Ñоединений Ñ ÑопоÑÑавлениÑми ÑÑÑок:
INNER JOINÐÐ»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑÑоки R1 из T1 в ÑезÑлÑÑиÑÑÑÑей ÑаблиÑе ÑодеÑжиÑÑÑ ÑÑÑока Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑÑоки в T2, ÑдовлеÑвоÑÑÑÑей ÑÑÐ»Ð¾Ð²Ð¸Ñ ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ R1.
LEFT OUTER JOINСнаÑала вÑполнÑеÑÑÑ Ð²Ð½ÑÑÑеннее Ñоединение (INNER JOIN). ÐаÑем в ÑезÑлÑÑÐ°Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÑÑÑÑ Ð²Ñе ÑÑÑоки из T1, коÑоÑÑм не ÑооÑвеÑÑÑвÑÑÑ Ð½Ð¸ÐºÐ°ÐºÐ¸Ðµ ÑÑÑоки в T2, а вмеÑÑо знаÑений ÑÑолбÑов T2 вÑÑавлÑÑÑÑÑ NULL. Таким обÑазом, в ÑезÑлÑÑиÑÑÑÑей ÑаблиÑе вÑегда бÑÐ´ÐµÑ Ð¼Ð¸Ð½Ð¸Ð¼Ñм одна ÑÑÑока Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑÑоки из T1.
RIGHT OUTER JOINСнаÑала вÑполнÑеÑÑÑ Ð²Ð½ÑÑÑеннее Ñоединение (INNER JOIN). ÐаÑем в ÑезÑлÑÑÐ°Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÑÑÑÑ Ð²Ñе ÑÑÑоки из T2, коÑоÑÑм не ÑооÑвеÑÑÑвÑÑÑ Ð½Ð¸ÐºÐ°ÐºÐ¸Ðµ ÑÑÑоки в T1, а вмеÑÑо знаÑений ÑÑолбÑов T1 вÑÑавлÑÑÑÑÑ NULL. ÐÑо Ñоединение ÑвлÑеÑÑÑ Ð¾Ð±ÑаÑнÑм к Ð»ÐµÐ²Ð¾Ð¼Ñ (LEFT JOIN): в ÑезÑлÑÑиÑÑÑÑей ÑаблиÑе вÑегда бÑÐ´ÐµÑ Ð¼Ð¸Ð½Ð¸Ð¼Ñм одна ÑÑÑока Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑÑоки из T2.
FULL OUTER JOINСнаÑала вÑполнÑеÑÑÑ Ð²Ð½ÑÑÑеннее Ñоединение. ÐаÑем в ÑезÑлÑÑÐ°Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÑÑÑÑ Ð²Ñе ÑÑÑоки из T1, коÑоÑÑм не ÑооÑвеÑÑÑвÑÑÑ Ð½Ð¸ÐºÐ°ÐºÐ¸Ðµ ÑÑÑоки в T2, а вмеÑÑо знаÑений ÑÑолбÑов T2 вÑÑавлÑÑÑÑÑ NULL. РнаконеÑ, в ÑезÑлÑÑÐ°Ñ Ð²ÐºÐ»ÑÑаÑÑÑÑ Ð²Ñе ÑÑÑоки из T2, коÑоÑÑм не ÑооÑвеÑÑÑвÑÑÑ Ð½Ð¸ÐºÐ°ÐºÐ¸Ðµ ÑÑÑоки в T1, а вмеÑÑо знаÑений ÑÑолбÑов T1 вÑÑавлÑÑÑÑÑ NULL.
ÐÑедложение
ONопÑеделÑÐµÑ Ð½Ð°Ð¸Ð±Ð¾Ð»ÐµÐµ обÑÑÑ ÑоÑÐ¼Ñ ÑÑÐ»Ð¾Ð²Ð¸Ñ ÑоединениÑ: в нÑм ÑказÑваÑÑÑÑ Ð²ÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð»Ð¾Ð³Ð¸ÑеÑкого Ñипа, подобнÑе Ñем, ÑÑо иÑполÑзÑÑÑÑÑ Ð² пÑедложенииWHERE. ÐаÑа ÑÑÑок изT1иT2ÑооÑвеÑÑÑвÑÑÑ Ð´ÑÑг дÑÑгÑ, еÑли вÑÑажениеONвозвÑаÑÐ°ÐµÑ Ð´Ð»Ñ Ð½Ð¸Ñ true.USINGâ ÑÑо ÑокÑаÑÑÐ½Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑ ÑÑловиÑ, Ð¿Ð¾Ð»ÐµÐ·Ð½Ð°Ñ Ð² ÑиÑÑаÑии, когда Ñ Ð¾Ð±ÐµÐ¸Ñ ÑÑоÑон ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ ÑÑолбÑÑ Ð¸Ð¼ÐµÑÑ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñе имена. Ðна пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ ÑпиÑок обÑÐ¸Ñ Ð¸Ð¼Ñн ÑÑолбÑов ÑеÑез запÑÑÑÑ Ð¸ ÑоÑмиÑÑÐµÑ ÑÑловие ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ ÑавенÑÑвом ÑÑÐ¸Ñ ÑÑолбÑов. ÐапÑимеÑ, запиÑÑ ÑоединениÑT1иT2ÑUSING (a, b)ÑоÑмиÑÑÐµÑ ÑÑловиеON.T1.a =T2.a ANDT1.b =T2.bÐолее Ñого, пÑи вÑводе
JOIN USINGиÑклÑÑаÑÑÑÑ Ð¸Ð·Ð±ÑÑоÑнÑе ÑÑолбÑÑ: оба ÑопоÑÑавленнÑÑ ÑÑолбÑа вÑводиÑÑ Ð½Ðµ нÑжно, Ñак как они ÑодеÑÐ¶Ð°Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñе знаÑениÑ. Тогда какJOIN ONвÑдаÑÑ Ð²Ñе ÑÑолбÑÑ Ð¸Ð·T1, а за ними вÑе ÑÑолбÑÑ Ð¸Ð·T2,JOIN USINGвÑÐ²Ð¾Ð´Ð¸Ñ Ð¾Ð´Ð¸Ð½ ÑÑÐ¾Ð»Ð±ÐµÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ паÑÑ (в Ñказанном поÑÑдке), за ними вÑе оÑÑавÑиеÑÑ ÑÑолбÑÑ Ð¸Ð·T1и, наконеÑ, вÑе оÑÑавÑиеÑÑ ÑÑолбÑÑT2.ÐаконеÑ,
NATURALâ ÑокÑаÑÑÐ½Ð½Ð°Ñ ÑоÑмаUSING: она обÑазÑÐµÑ ÑпиÑокUSINGиз вÑÐµÑ Ð¸Ð¼Ñн ÑÑолбÑов, ÑÑÑеÑÑвÑÑÑÐ¸Ñ Ð² Ð¾Ð±ÐµÐ¸Ñ Ð²Ñ Ð¾Ð´Ð½ÑÑ ÑаблиÑÐ°Ñ . Ðак и ÑUSING, ÑÑи ÑÑолбÑÑ Ð¾ÐºÐ°Ð·ÑваÑÑÑÑ Ð² вÑÑ Ð¾Ð´Ð½Ð¾Ð¹ ÑаблиÑе в единÑÑвенном ÑкземплÑÑе. ÐÑли ÑÑолбÑов Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñми именами не Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ,NATURAL JOINдейÑÑвÑÐµÑ ÐºÐ°ÐºJOIN ... ON TRUEи вÑдаÑÑ Ð´ÐµÐºÐ°ÑÑово пÑоизведение ÑÑÑок.ÐÑимеÑание
ÐÑедложение
USINGÑазÑмно заÑиÑено Ð¾Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹ в ÑоединÑемÑÑ Ð¾ÑноÑениÑÑ , Ñак как оно ÑвÑзÑÐ²Ð°ÐµÑ ÑолÑко Ñвно пеÑеÑиÑленнÑе ÑÑолбÑÑ.NATURALÑÑиÑаеÑÑÑ Ð±Ð¾Ð»ÐµÐµ ÑиÑкованнÑм, Ñак как пÑи лÑбом изменении ÑÑ ÐµÐ¼Ñ Ð² одном или дÑÑгом оÑноÑении, когда поÑвлÑÑÑÑÑ ÑÑолбÑÑ Ñ ÑовпадаÑÑими именами, пÑи Ñоединении бÑдÑÑ ÑвÑзÑваÑÑÑÑ Ð¸ ÑÑи новÑе ÑÑолбÑÑ.
ÐÐ»Ñ Ð½Ð°Ð³Ð»ÑдноÑÑи пÑедположим, ÑÑо Ñ Ð½Ð°Ñ ÐµÑÑÑ ÑаблиÑÑ t1:
num | name -----+------ 1 | a 2 | b 3 | c
и t2:
num | value -----+------- 1 | xxx 3 | yyy 5 | zzz
С ними Ð´Ð»Ñ ÑазнÑÑ Ñипов Ñоединений Ð¼Ñ Ð¿Ð¾Ð»ÑÑим ÑледÑÑÑие ÑезÑлÑÑаÑÑ:
=>SELECT * FROM t1 CROSS JOIN t2;num | name | num | value -----+------+-----+------- 1 | a | 1 | xxx 1 | a | 3 | yyy 1 | a | 5 | zzz 2 | b | 1 | xxx 2 | b | 3 | yyy 2 | b | 5 | zzz 3 | c | 1 | xxx 3 | c | 3 | yyy 3 | c | 5 | zzz (9 rows)=>SELECT * FROM t1 INNER JOIN t2 ON t1.num = t2.num;num | name | num | value -----+------+-----+------- 1 | a | 1 | xxx 3 | c | 3 | yyy (2 rows)=>SELECT * FROM t1 INNER JOIN t2 USING (num);num | name | value -----+------+------- 1 | a | xxx 3 | c | yyy (2 rows)=>SELECT * FROM t1 NATURAL INNER JOIN t2;num | name | value -----+------+------- 1 | a | xxx 3 | c | yyy (2 rows)=>SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num;num | name | num | value -----+------+-----+------- 1 | a | 1 | xxx 2 | b | | 3 | c | 3 | yyy (3 rows)=>SELECT * FROM t1 LEFT JOIN t2 USING (num);num | name | value -----+------+------- 1 | a | xxx 2 | b | 3 | c | yyy (3 rows)=>SELECT * FROM t1 RIGHT JOIN t2 ON t1.num = t2.num;num | name | num | value -----+------+-----+------- 1 | a | 1 | xxx 3 | c | 3 | yyy | | 5 | zzz (3 rows)=>SELECT * FROM t1 FULL JOIN t2 ON t1.num = t2.num;num | name | num | value -----+------+-----+------- 1 | a | 1 | xxx 2 | b | | 3 | c | 3 | yyy | | 5 | zzz (4 rows)
УÑловие ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ð² пÑедложении ON Ð¼Ð¾Ð¶ÐµÑ Ñакже ÑодеÑжаÑÑ Ð²ÑÑажениÑ, не ÑвÑзаннÑе непоÑÑедÑÑвенно Ñ Ñоединением. ÐÑо Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾ в некоÑоÑÑÑ
запÑоÑаÑ
, но не ÑледÑÐµÑ Ð¸ÑполÑзоваÑÑ ÑÑо необдÑманно. РаÑÑмоÑÑиÑе ÑледÑÑÑий запÑоÑ:
=>SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num AND t2.value = 'xxx';num | name | num | value -----+------+-----+------- 1 | a | 1 | xxx 2 | b | | 3 | c | | (3 rows)
ÐамеÑÑÑе, ÑÑо еÑли помеÑÑиÑÑ Ð¾Ð³ÑаниÑение в пÑедложение WHERE, Ð²Ñ Ð¿Ð¾Ð»ÑÑиÑе дÑÑгой ÑезÑлÑÑаÑ:
=>SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num WHERE t2.value = 'xxx';num | name | num | value -----+------+-----+------- 1 | a | 1 | xxx (1 row)
ÐÑо ÑвÑзано Ñ Ñем, ÑÑо огÑаниÑение, помеÑÑнное в пÑедложение ON, обÑабаÑÑваеÑÑÑ Ð´Ð¾ опеÑаÑии ÑоединениÑ, Ñогда как огÑаниÑение в WHERE â поÑле. ÐÑо не Ð¸Ð¼ÐµÐµÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð¿Ñи внÑÑÑенниÑ
ÑоединениÑÑ
, но важно пÑи внеÑниÑ
.
7.2.1.2. ÐÑÐµÐ²Ð´Ð¾Ð½Ð¸Ð¼Ñ ÑÐ°Ð±Ð»Ð¸Ñ Ð¸ ÑÑолбÑов #
ТаблиÑам и ÑÑÑлкам на ÑложнÑе ÑаблиÑÑ Ð² запÑоÑе можно даÑÑ Ð²Ñеменное имÑ, по коÑоÑÐ¾Ð¼Ñ Ðº ним можно бÑÐ´ÐµÑ Ð¾Ð±ÑаÑаÑÑÑÑ Ð² ÑÐ°Ð¼ÐºÐ°Ñ Ð·Ð°Ð¿ÑоÑа. Такое Ð¸Ð¼Ñ Ð½Ð°Ð·ÑваеÑÑÑ Ð¿Ñевдонимом ÑаблиÑÑ.
ÐпÑеделиÑÑ Ð¿Ñевдоним ÑаблиÑÑ Ð¼Ð¾Ð¶Ð½Ð¾, напиÑав
FROMÑаблиÑнаÑ_ÑÑÑлкаASпÑевдоним
или
FROMÑаблиÑнаÑ_ÑÑÑлкапÑевдоним
ÐлÑÑевое Ñлово AS ÑвлÑеÑÑÑ Ð½ÐµÐ¾Ð±ÑзаÑелÑнÑм. ÐмеÑÑо пÑевдоним здеÑÑ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð»Ñбой иденÑиÑикаÑоÑ.
ÐÑÐµÐ²Ð´Ð¾Ð½Ð¸Ð¼Ñ ÑаÑÑо пÑименÑÑÑÑÑ Ð´Ð»Ñ Ð½Ð°Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ ÐºÐ¾ÑоÑÐºÐ¸Ñ Ð¸Ð´ÐµÐ½ÑиÑикаÑоÑов длиннÑм именам ÑÐ°Ð±Ð»Ð¸Ñ Ñ ÑелÑÑ ÑлÑÑÑÐµÐ½Ð¸Ñ ÑиÑаемоÑÑи запÑоÑов. ÐапÑимеÑ:
SELECT * FROM "оÑенÑ_длинное_имÑ_ÑаблиÑÑ" s JOIN "дÑÑгое_длинное_имÑ" a ON s.id = a.num;
ÐÑевдоним ÑÑановиÑÑÑ Ð½Ð¾Ð²Ñм именем ÑаблиÑÑ Ð² ÑÐ°Ð¼ÐºÐ°Ñ ÑекÑÑего запÑоÑа, Ñ. е. поÑле назнаÑÐµÐ½Ð¸Ñ Ð¿Ñевдонима иÑполÑзоваÑÑ Ð¸ÑÑ Ð¾Ð´Ð½Ð¾Ðµ Ð¸Ð¼Ñ ÑаблиÑÑ Ð² дÑÑгом меÑÑе запÑоÑа нелÑзÑ. Таким обÑазом, ÑледÑÑÑий запÑÐ¾Ñ Ð½ÐµÐ´Ð¾Ð¿ÑÑÑим:
SELECT * FROM my_table AS m WHERE my_table.a > 5; -- непÑавилÑно
ХоÑÑ Ð² оÑновном пÑÐµÐ²Ð´Ð¾Ð½Ð¸Ð¼Ñ Ð¸ÑполÑзÑÑÑÑÑ Ð´Ð»Ñ ÑдобÑÑва, они бÑваÑÑ Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ñ, когда ÑаблиÑа ÑоединÑеÑÑÑ Ñама Ñ Ñобой, напÑимеÑ:
SELECT * FROM people AS mother JOIN people AS child ON mother.id = child.mother_id;
Ð ÑлÑÑае неоднознаÑноÑÑи опÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ñевдонимов можно иÑполÑзоваÑÑ Ñкобки. Ð ÑледÑÑÑем пÑимеÑе пеÑвÑй опеÑаÑÐ¾Ñ Ð½Ð°Ð·Ð½Ð°ÑÐ°ÐµÑ Ð¿Ñевдоним b вÑоÑÐ¾Ð¼Ñ ÑкземплÑÑÑ my_table, а вÑоÑой опеÑаÑÐ¾Ñ Ð½Ð°Ð·Ð½Ð°ÑÐ°ÐµÑ Ð¿Ñевдоним ÑезÑлÑÑаÑÑ ÑоединениÑ:
SELECT * FROM my_table AS a CROSS JOIN my_table AS b ... SELECT * FROM (my_table AS a CROSS JOIN my_table) AS b ...
РдÑÑгой ÑоÑме назнаÑÐµÐ½Ð¸Ñ Ð¿Ñевдонима вÑеменнÑе имена даÑÑÑÑ Ð½Ðµ ÑолÑко ÑаблиÑам, но и ÐµÑ ÑÑолбÑам:
FROMÑаблиÑнаÑ_ÑÑÑлка[AS]пÑевдоним(ÑÑолбеÑ1[,ÑÑолбеÑ2[, ...]] )
ÐÑли пÑевдонимов ÑÑолбÑов оказÑваеÑÑÑ Ð¼ÐµÐ½ÑÑе, Ñем ÑакÑиÑеÑки ÑÑолбÑов в ÑаблиÑе, оÑÑалÑнÑе ÑÑолбÑÑ ÑÐ¾Ñ ÑанÑÑÑ Ñвои иÑÑ Ð¾Ð´Ð½Ñе имена. ÐÑа запиÑÑ Ð¾Ñобенно полезна Ð´Ð»Ñ Ð·Ð°Ð¼ÐºÐ½ÑÑÑÑ Ñоединений или подзапÑоÑов.
Ðогда пÑевдоним пÑименÑеÑÑÑ Ðº ÑезÑлÑÑаÑÑ JOIN, он ÑкÑÑÐ²Ð°ÐµÑ Ð¾ÑигиналÑнÑе имена ÑÐ°Ð±Ð»Ð¸Ñ Ð²Ð½ÑÑÑи JOIN. ÐапÑимеÑ, ÑÑо допÑÑÑимÑй SQL-запÑоÑ:
SELECT a.* FROM my_table AS a JOIN your_table AS b ON ...
а запÑоÑ:
SELECT a.* FROM (my_table AS a JOIN your_table AS b ON ...) AS c
оÑибоÑнÑй, Ñак как пÑевдоним ÑаблиÑÑ a не виден ÑнаÑÑжи опÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ñевдонима c.
7.2.1.3. ÐодзапÑоÑÑ #
ÐодзапÑоÑÑ, обÑазÑÑÑие ÑаблиÑÑ, Ð´Ð¾Ð»Ð¶Ð½Ñ Ð·Ð°ÐºÐ»ÑÑаÑÑÑÑ Ð² Ñкобки. Ðм могÑÑ Ð½Ð°Ð·Ð½Ð°ÑаÑÑÑÑ Ð¿ÑÐµÐ²Ð´Ð¾Ð½Ð¸Ð¼Ñ ÑÐ°Ð±Ð»Ð¸Ñ Ð¸, еÑли Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾, пÑÐµÐ²Ð´Ð¾Ð½Ð¸Ð¼Ñ ÑÑолбÑов (как опиÑано в ÐодÑазделе 7.2.1.2). ÐапÑимеÑ:
FROM (SELECT * FROM table1) AS пÑевдоним
ÐÑÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ ÑавноÑилен запиÑи FROM table1 AS пÑевдоним. Ðолее инÑеÑеÑнÑе ÑиÑÑаÑии, коÑоÑÑе нелÑÐ·Ñ ÑвеÑÑи к пÑоÑÑÐ¾Ð¼Ñ ÑоединениÑ, возникаÑÑ, когда в подзапÑоÑе иÑполÑзÑÑÑÑÑ Ð°Ð³ÑегиÑÑÑÑие ÑÑнкÑии или гÑÑппиÑовка.
ÐодзапÑоÑом Ð¼Ð¾Ð¶ÐµÑ Ñакже бÑÑÑ ÑпиÑок VALUES:
FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow'))
AS names(first, last) Ð¢Ð°ÐºÐ¾Ð¼Ñ Ð¿Ð¾Ð´Ð·Ð°Ð¿ÑоÑÑ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð½Ð°Ð·Ð½Ð°Ñен пÑевдоним. ÐазнаÑаÑÑ Ð¿ÑÐµÐ²Ð´Ð¾Ð½Ð¸Ð¼Ñ ÑÑолбÑам ÑпиÑка VALUES не ÑÑебÑеÑÑÑ, но вообÑе ÑÑо Ñ
оÑоÑий пÑиÑм. ÐодÑобнее ÑÑо опиÑано в Разделе 7.7.
СоглаÑно ÑÑандаÑÑÑ SQL подзапÑоÑÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ назнаÑаÑÑÑÑ Ð¿Ñевдоним ÑаблиÑÑ. Postgres Pro позволÑÐµÑ Ð¾Ð¿ÑÑкаÑÑ AS и пÑевдоним, Ñем не менее Ñ
оÑоÑей пÑакÑикой ÑÑиÑаеÑÑÑ ÑказÑваÑÑ Ð¿Ñевдоним в коде SQL, коÑоÑÑй Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾ÑÑиÑован в дÑÑгÑÑ ÑиÑÑемÑ.
7.2.1.4. ТаблиÑнÑе ÑÑнкÑии #
ТаблиÑнÑе ÑÑнкÑии â ÑÑо ÑÑнкÑии, вÑдаÑÑие Ð½Ð°Ð±Ð¾Ñ ÑÑÑок, ÑодеÑжаÑиÑ
либо базовÑе ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ
(ÑкалÑÑнÑÑ
Ñипов), либо ÑоÑÑавнÑе ÑÐ¸Ð¿Ñ (ÑаблиÑнÑе ÑÑÑоки). Ðни пÑименÑÑÑÑÑ Ð² запÑоÑаÑ
как ÑаблиÑÑ, пÑедÑÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ подзапÑоÑÑ Ð² пÑедложении FROM. СÑолбÑÑ, возвÑаÑÑннÑе ÑаблиÑнÑми ÑÑнкÑиÑми, можно вклÑÑиÑÑ Ð² вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ SELECT, JOIN или WHERE Ñак же, как ÑÑолбÑÑ ÑаблиÑ, пÑедÑÑавлений или подзапÑоÑов.
ТаблиÑнÑе ÑÑнкÑии можно Ñакже ÑкомбиниÑоваÑÑ, иÑполÑзÑÑ Ð·Ð°Ð¿Ð¸ÑÑ ROWS FROM. РезÑлÑÑаÑÑ ÑÑнкÑий бÑдÑÑ Ð²Ð¾Ð·Ð²ÑаÑÐµÐ½Ñ Ð² паÑаллелÑнÑÑ
ÑÑолбÑаÑ
; ÑиÑло ÑÑÑок в ÑÑом ÑлÑÑае бÑÐ´ÐµÑ Ð½Ð°Ð¸Ð±Ð¾Ð»ÑÑим из ÑезÑлÑÑаÑов вÑеÑ
ÑÑнкÑий, а ÑезÑлÑÑаÑÑ ÑÑнкÑий Ñ Ð¼ÐµÐ½ÑÑим колиÑеÑÑвом ÑÑÑок бÑдÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ñ Ð·Ð½Ð°ÑениÑми NULL.
вÑзов_ÑÑнкÑии[WITH ORDINALITY] [[AS]пÑевдоним_ÑаблиÑÑ[(пÑевдоним_ÑÑолбÑа[, ...])]] ROWS FROM(вÑзов_ÑÑнкÑии[, ...] ) [WITH ORDINALITY] [[AS]пÑевдоним_ÑаблиÑÑ[(пÑевдоним_ÑÑолбÑа[, ...])]]
ÐÑли Ñказано пÑедложение WITH ORDINALITY, к ÑÑолбÑам ÑезÑлÑÑаÑов ÑÑнкÑий бÑÐ´ÐµÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½ еÑÑ Ð¾Ð´Ð¸Ð½, Ñ Ñипом bigint. Ð ÑÑом ÑÑолбÑе нÑмеÑÑÑÑÑÑ ÑÑÑоки ÑезÑлÑÑиÑÑÑÑего набоÑа, наÑÐ¸Ð½Ð°Ñ Ñ 1. (ÐÑо обобÑение ÑÑандаÑÑного SQL-ÑинÑакÑиÑа UNNEST ... WITH ORDINALITY.) Ðо ÑмолÑаниÑ, ÑÑÐ¾Ñ ÑÑÐ¾Ð»Ð±ÐµÑ Ð½Ð°Ð·ÑваеÑÑÑ ordinality, но ÐµÐ¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ пÑиÑвоиÑÑ Ð¸ дÑÑгое Ð¸Ð¼Ñ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑÐºÐ°Ð·Ð°Ð½Ð¸Ñ AS.
СпеÑиалÑнÑÑ ÑаблиÑнÑÑ ÑÑнкÑÐ¸Ñ UNNEST можно вÑзваÑÑ Ñ Ð»ÑбÑм ÑиÑлом паÑамеÑÑов-маÑÑивов, а возвÑаÑÐ°ÐµÑ Ð¾Ð½Ð° ÑооÑвеÑÑÑвÑÑÑее ÑиÑло ÑÑолбÑов, как еÑли Ð±Ñ UNNEST (Раздел 9.19) вÑзÑвалаÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ паÑамеÑÑа в оÑделÑноÑÑи, а ÑезÑлÑÑаÑÑ Ð¾Ð±ÑединÑлиÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑии ROWS FROM.
UNNEST(вÑÑажение_маÑÑива[, ...] ) [WITH ORDINALITY] [[AS]пÑевдоним_ÑаблиÑÑ[(пÑевдоним_ÑÑолбÑа[, ...])]]
ÐÑли пÑевдоним_ÑаблиÑÑ Ð½Ðµ Ñказан, в каÑеÑÑве имени ÑаблиÑÑ Ð¸ÑполÑзÑеÑÑÑ Ð¸Ð¼Ñ ÑÑнкÑии; в ÑлÑÑае Ñ ÐºÐ¾Ð½ÑÑÑÑкÑией ROWS FROM() â Ð¸Ð¼Ñ Ð¿ÐµÑвой ÑÑнкÑии.
ÐÑли пÑÐµÐ²Ð´Ð¾Ð½Ð¸Ð¼Ñ ÑÑолбÑов не ÑказанÑ, Ñо Ð´Ð»Ñ ÑÑнкÑии, возвÑаÑаÑÑей базовÑй Ñип даннÑÑ , именем ÑÑолбÑа бÑÐ´ÐµÑ Ð¸Ð¼Ñ ÑÑнкÑии. ÐÐ»Ñ ÑÑнкÑий, возвÑаÑаÑÑÐ¸Ñ ÑоÑÑавной Ñип, имена ÑезÑлÑÑиÑÑÑÑÐ¸Ñ ÑÑолбÑов опÑеделÑÑÑÑÑ Ð¸Ð½Ð´Ð¸Ð²Ð¸Ð´ÑалÑнÑми аÑÑибÑÑами Ñипа.
ÐеÑколÑко пÑимеÑов:
CREATE TABLE foo (fooid int, foosubid int, fooname text);
CREATE FUNCTION getfoo(int) RETURNS SETOF foo AS $$
SELECT * FROM foo WHERE fooid = $1;
$$ LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1;
SELECT * FROM foo
WHERE foosubid IN (
SELECT foosubid
FROM getfoo(foo.fooid) z
WHERE z.fooid = foo.fooid
);
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;РнекоÑоÑÑÑ
ÑлÑÑаÑÑ
бÑÐ²Ð°ÐµÑ Ñдобно опÑеделиÑÑ ÑаблиÑнÑÑ ÑÑнкÑиÑ, возвÑаÑаÑÑÑÑ ÑазлиÑнÑе набоÑÑ ÑÑолбÑов пÑи ÑазнÑÑ
ваÑианÑаÑ
вÑзова. ÐÑо можно ÑделаÑÑ, обÑÑвив ÑÑнкÑиÑ, не имеÑÑÑÑ Ð²ÑÑ
однÑÑ
паÑамеÑÑов (OUT) и возвÑаÑаÑÑÑÑ Ð¿ÑевдоÑип record. ÐÑполÑзÑÑ ÑакÑÑ ÑÑнкÑиÑ, ожидаемÑÑ ÑÑÑÑкÑÑÑÑ ÑÑÑок нÑжно опиÑаÑÑ Ð² Ñамом запÑоÑе, ÑÑÐ¾Ð±Ñ ÑиÑÑема знала, как ÑазобÑаÑÑ Ð·Ð°Ð¿ÑÐ¾Ñ Ð¸ ÑоÑÑавиÑÑ ÐµÐ³Ð¾ план. ÐапиÑÑваеÑÑÑ ÑÑо Ñак:
вÑзов_ÑÑнкÑии[AS]пÑевдоним(опÑеделение_ÑÑолбÑа[, ...])вÑзов_ÑÑнкÑииAS [пÑевдоним] (опÑеделение_ÑÑолбÑа[, ...]) ROWS FROM( ...вÑзов_ÑÑнкÑииAS (опÑеделение_ÑÑолбÑа[, ...]) [, ...] )
Ðез ROWS FROM() ÑпиÑок опÑеделениÑ_ÑÑолбÑов заменÑÐµÑ ÑпиÑок пÑевдонимов, коÑоÑÑй можно Ñакже добавиÑÑ Ð² пÑедложении FROM; имена в опÑеделениÑÑ
ÑÑолбÑов ÑлÑÐ¶Ð°Ñ Ð¿Ñевдонимами. С ROWS FROM() ÑпиÑок опÑеделениÑ_ÑÑолбÑов можно добавиÑÑ Ðº каждой ÑÑнкÑии оÑделÑно, либо в ÑлÑÑае Ñ Ð¾Ð´Ð½Ð¾Ð¹ ÑÑнкÑией и без пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ WITH ORDINALITY, ÑпиÑок опÑеделениÑ_ÑÑолбÑов можно запиÑаÑÑ Ð²Ð¼ÐµÑÑо ÑпиÑка Ñ Ð¿Ñевдонимами ÑÑолбÑов поÑле ROWS FROM().
ÐзглÑниÑе на ÑÑÐ¾Ñ Ð¿ÑимеÑ:
SELECT *
FROM dblink('dbname=mydb', 'SELECT proname, prosrc FROM pg_proc')
AS t1(proname name, prosrc text)
WHERE proname LIKE 'bytea%'; ÐдеÑÑ ÑÑнкÑÐ¸Ñ dblink (из модÑÐ»Ñ dblink) вÑполнÑÐµÑ ÑдалÑннÑй запÑоÑ. Ðна обÑÑвлена как ÑÑнкÑиÑ, возвÑаÑаÑÑÐ°Ñ Ñип record, Ñак как он подойдÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿ÑоÑа лÑбого Ñипа. Ð ÑÑом ÑлÑÑае ÑакÑиÑеÑкий Ð½Ð°Ð±Ð¾Ñ ÑÑолбÑов ÑÑнкÑии необÑ
одимо опиÑаÑÑ Ð² вÑзÑваÑÑем ÐµÑ Ð·Ð°Ð¿ÑоÑе, ÑÑÐ¾Ð±Ñ Ð°Ð½Ð°Ð»Ð¸Ð·Ð°ÑÐ¾Ñ Ð·Ð°Ð¿ÑоÑа знал, напÑимеÑ, как пÑеобÑазоваÑÑ *.
Ð ÑÑом пÑимеÑе иÑполÑзÑеÑÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¸Ñ ROWS FROM:
SELECT *
FROM ROWS FROM
(
json_to_recordset('[{"a":40,"b":"foo"},{"a":"100","b":"bar"}]')
AS (a INTEGER, b TEXT),
generate_series(1, 3)
) AS x (p, q, s)
ORDER BY p;
p | q | s
-----+-----+---
40 | foo | 1
100 | bar | 2
| | 3 Ðна обÑединÑÐµÑ ÑезÑлÑÑаÑÑ Ð´Ð²ÑÑ
ÑÑнкÑий в одном оÑноÑении FROM. Рданном ÑлÑÑае json_to_recordset() должна вÑдаваÑÑ Ð´Ð²Ð° ÑÑолбÑа, пеÑвÑй integer и вÑоÑой text, а ÑезÑлÑÑÐ°Ñ generate_series() иÑполÑзÑеÑÑÑ Ð½ÐµÐ¿Ð¾ÑÑедÑÑвенно. ÐÑедложение ORDER BY ÑпоÑÑдоÑÐ¸Ð²Ð°ÐµÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð¿ÐµÑвого ÑÑолбÑа как ÑелоÑиÑленнÑе.
7.2.1.5. ÐодзапÑоÑÑ LATERAL #
ÐеÑед подзапÑоÑами в пÑедложении FROM можно добавиÑÑ ÐºÐ»ÑÑевое Ñлово LATERAL. ÐÑо Ð¿Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ ÑÑÑлаÑÑÑÑ Ð² ниÑ
на ÑÑолбÑÑ Ð¿ÑедÑеÑÑвÑÑÑиÑ
ÑлеменÑов ÑпиÑка FROM. (Ðез LATERAL каждÑй подзапÑÐ¾Ñ Ð²ÑполнÑеÑÑÑ Ð½ÐµÐ·Ð°Ð²Ð¸Ñимо и поÑÑÐ¾Ð¼Ñ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ð¾Ð±ÑаÑаÑÑÑÑ Ðº дÑÑгим ÑлеменÑам FROM.)
ÐеÑед ÑаблиÑнÑми ÑÑнкÑиÑми в пÑедложении FROM Ñакже можно ÑказаÑÑ LATERAL, но Ð´Ð»Ñ Ð½Ð¸Ñ
ÑÑо клÑÑевое Ñлово необÑзаÑелÑно; в аÑгÑменÑаÑ
ÑÑнкÑий в лÑбом ÑлÑÑае можно обÑаÑаÑÑÑÑ Ðº ÑÑолбÑам в пÑедÑдÑÑиÑ
ÑлеменÑаÑ
FROM.
ÐÐ»ÐµÐ¼ÐµÐ½Ñ LATERAL Ð¼Ð¾Ð¶ÐµÑ Ð½Ð°Ñ
одиÑÑÑÑ Ð½Ð° веÑÑ
нем ÑÑовне ÑпиÑка FROM или в деÑеве JOIN. РпоÑледнем ÑлÑÑае он Ð¼Ð¾Ð¶ÐµÑ Ñакже ÑÑÑлаÑÑÑÑ Ð½Ð° лÑбÑе ÑлеменÑÑ Ð² левой ÑаÑÑи JOIN, ÑпÑава Ð¾Ñ ÐºÐ¾ÑоÑого он наÑ
одиÑÑÑ.
Ðогда ÑÐ»ÐµÐ¼ÐµÐ½Ñ FROM ÑодеÑÐ¶Ð¸Ñ ÑÑÑлки LATERAL, запÑÐ¾Ñ Ð²ÑполнÑеÑÑÑ ÑледÑÑÑим обÑазом: ÑнаÑала Ð´Ð»Ñ ÑÑÑоки ÑлеменÑа FROM Ñ ÑелевÑми ÑÑолбÑами, или набоÑа ÑÑÑок из неÑколÑкиÑ
ÑлеменÑов FROM, ÑодеÑжаÑиÑ
ÑелевÑе ÑÑолбÑÑ, вÑÑиÑлÑеÑÑÑ ÑÐ»ÐµÐ¼ÐµÐ½Ñ LATERAL Ñо знаÑениÑми ÑÑиÑ
ÑÑолбÑов. ÐаÑем ÑезÑлÑÑиÑÑÑÑие ÑÑÑоки обÑÑнÑм обÑазом ÑоединÑÑÑÑÑ Ñо ÑÑÑоками, из коÑоÑÑÑ
они бÑли вÑÑиÑленÑ. ÐÑа пÑоÑедÑÑа повÑоÑÑеÑÑÑ Ð´Ð»Ñ Ð²ÑеÑ
ÑÑÑок иÑÑ
однÑÑ
ÑаблиÑ.
LATERAL можно иÑполÑзоваÑÑ Ñак:
SELECT * FROM foo, LATERAL (SELECT * FROM bar WHERE bar.id = foo.bar_id) ss;
ÐдеÑÑ ÑÑо не оÑÐµÐ½Ñ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾, Ñак как ÑÐ¾Ñ Ð¶Ðµ ÑезÑлÑÑÐ°Ñ Ð¼Ð¾Ð¶Ð½Ð¾ полÑÑиÑÑ Ð±Ð¾Ð»ÐµÐµ пÑоÑÑÑм и пÑивÑÑнÑм ÑпоÑобом:
SELECT * FROM foo, bar WHERE bar.id = foo.bar_id;
ÐÑименÑÑÑ LATERAL Ð¸Ð¼ÐµÐµÑ ÑмÑÑл в оÑновном, когда Ð´Ð»Ñ Ð²ÑÑиÑÐ»ÐµÐ½Ð¸Ñ ÑоединÑемÑÑ
ÑÑÑок необÑ
одимо обÑаÑиÑÑÑÑ Ðº ÑÑолбÑам дÑÑгиÑ
ÑаблиÑ. Ð ÑаÑÑноÑÑи, ÑÑо полезно, когда нÑжно пеÑедаÑÑ Ð·Ð½Ð°Ñение ÑÑнкÑии, возвÑаÑаÑÑей Ð½Ð°Ð±Ð¾Ñ Ð´Ð°Ð½Ð½ÑÑ
. ÐапÑимеÑ, еÑли пÑедположиÑÑ, ÑÑо vertices(polygon) возвÑаÑÐ°ÐµÑ Ð½Ð°Ð±Ð¾Ñ Ð²ÐµÑÑин многоÑголÑника, близкие веÑÑÐ¸Ð½Ñ Ð¼Ð½Ð¾Ð³Ð¾ÑголÑников из ÑаблиÑÑ polygons можно полÑÑиÑÑ Ñак:
SELECT p1.id, p2.id, v1, v2
FROM polygons p1, polygons p2,
LATERAL vertices(p1.poly) v1,
LATERAL vertices(p2.poly) v2
WHERE (v1 <-> v2) < 10 AND p1.id != p2.id;ÐÑÐ¾Ñ Ð·Ð°Ð¿ÑÐ¾Ñ Ð¼Ð¾Ð¶Ð½Ð¾ запиÑаÑÑ Ð¸ Ñак:
SELECT p1.id, p2.id, v1, v2
FROM polygons p1 CROSS JOIN LATERAL vertices(p1.poly) v1,
polygons p2 CROSS JOIN LATERAL vertices(p2.poly) v2
WHERE (v1 <-> v2) < 10 AND p1.id != p2.id; или пеÑеÑоÑмÑлиÑоваÑÑ Ð´ÑÑгими ÑпоÑобами. (Ðак Ñже ÑпоминалоÑÑ, в данном пÑимеÑе клÑÑевое Ñлово LATERAL не ÑÑебÑеÑÑÑ, но Ð¼Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ð»Ð¸ его Ð´Ð»Ñ ÑÑноÑÑи.)
ÐÑобенно полезно бÑÐ²Ð°ÐµÑ Ð¸ÑполÑзоваÑÑ LEFT JOIN Ñ Ð¿Ð¾Ð´Ð·Ð°Ð¿ÑоÑом LATERAL, ÑÑÐ¾Ð±Ñ Ð¸ÑÑ
однÑе ÑÑÑоки оказÑвалиÑÑ Ð² ÑезÑлÑÑаÑе, даже еÑли подзапÑÐ¾Ñ LATERAL не возвÑаÑÐ°ÐµÑ ÑÑÑок. ÐапÑимеÑ, еÑли ÑÑнкÑÐ¸Ñ get_product_names() вÑдаÑÑ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ð¿ÑодÑкÑов, вÑпÑÑеннÑÑ
опÑеделÑннÑм пÑоизводиÑелем, но о пÑодÑкÑии некоÑоÑÑÑ
пÑоизводиÑелей инÑоÑмаÑии неÑ, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ найÑи, какиÑ
именно, пÑимеÑно Ñак:
SELECT m.name FROM manufacturers m LEFT JOIN LATERAL get_product_names(m.id) pname ON true WHERE pname IS NULL;
7.2.2. ÐÑедложение WHERE #
ÐÑедложение WHERE запиÑÑваеÑÑÑ Ñак:
WHERE ÑÑловие_огÑаниÑениÑ
где ÑÑловие_огÑаниÑÐµÐ½Ð¸Ñ â лÑбое вÑÑажение знаÑÐµÐ½Ð¸Ñ (Ñм. Раздел 4.2), вÑдаÑÑее ÑезÑлÑÑÐ°Ñ Ñипа boolean.
ÐоÑле обÑабоÑки пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ FROM ÐºÐ°Ð¶Ð´Ð°Ñ ÑÑÑока полÑÑенной виÑÑÑалÑной ÑаблиÑÑ Ð¿ÑоÑ
Ð¾Ð´Ð¸Ñ Ð¿ÑовеÑÐºÑ Ð¿Ð¾ ÑÑÐ»Ð¾Ð²Ð¸Ñ Ð¾Ð³ÑаниÑениÑ. ÐÑли ÑезÑлÑÑÐ°Ñ ÑÑÐ»Ð¾Ð²Ð¸Ñ Ñавен true, ÑÑа ÑÑÑока оÑÑаÑÑÑÑ Ð² вÑÑ
одной ÑаблиÑе, а инаÑе (еÑли ÑезÑлÑÑÐ°Ñ Ñавен false или NULL) оÑбÑаÑÑваеÑÑÑ. Ð ÑÑловии огÑаниÑениÑ, как пÑавило, задейÑÑвÑеÑÑÑ Ð¼Ð¸Ð½Ð¸Ð¼Ñм один ÑÑÐ¾Ð»Ð±ÐµÑ Ð¸Ð· ÑаблиÑÑ, полÑÑенной на вÑÑ
оде FROM. ХоÑÑ ÑÑÑого говоÑÑ, ÑÑо не ÑÑебÑеÑÑÑ, но в пÑоÑивном ÑлÑÑае пÑедложение WHERE бÑÐ´ÐµÑ Ð±ÐµÑÑмÑÑленнÑм.
ÐÑимеÑание
УÑловие Ð´Ð»Ñ Ð²Ð½ÑÑÑеннего ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ запиÑаÑÑ ÐºÐ°Ðº в пÑедложении WHERE, Ñак и в пÑедложении JOIN. ÐапÑимеÑ, ÑÑо вÑÑажение:
FROM a, b WHERE a.id = b.id AND b.val > 5
ÑавнознаÑно ÑÑомÑ:
FROM a INNER JOIN b ON (a.id = b.id) WHERE b.val > 5
и возможно, даже ÑÑомÑ:
FROM a NATURAL JOIN b WHERE b.val > 5
Ðакой ваÑÐ¸Ð°Ð½Ñ Ð²ÑбÑаÑÑ, в оÑновном дело вкÑÑа и ÑÑилÑ. ÐаÑÐ¸Ð°Ð½Ñ Ñ JOIN внÑÑÑи пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ FROM, возможно, не лÑÑÑий Ñ ÑоÑки зÑÐµÐ½Ð¸Ñ ÑовмеÑÑимоÑÑи Ñ Ð´ÑÑгими СУÐÐ, Ñ
оÑÑ Ð¾Ð½ и опиÑан в ÑÑандаÑÑе SQL. Ðо Ð´Ð»Ñ Ð²Ð½ÐµÑниÑ
Ñоединений дÑÑгиÑ
ваÑианÑов неÑ: иÑ
можно запиÑÑваÑÑ ÑолÑко во FROM. ÐÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ON и USING во внеÑниÑ
ÑоединениÑÑ
не ÑавнознаÑÐ½Ñ ÑÑÐ»Ð¾Ð²Ð¸Ñ WHERE, Ñак как они могÑÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÑÑ ÑÑÑоки (Ð´Ð»Ñ Ð²Ñ
однÑÑ
ÑÑÑок без ÑооÑвеÑÑÑвиÑ), а Ñакже ÑдалÑÑÑ Ð¸Ñ
из конеÑного ÑезÑлÑÑаÑа.
ÐеÑколÑко пÑимеÑов запÑоÑов Ñ WHERE:
SELECT ... FROM fdt WHERE c1 > 5 SELECT ... FROM fdt WHERE c1 IN (1, 2, 3) SELECT ... FROM fdt WHERE c1 IN (SELECT c1 FROM t2) SELECT ... FROM fdt WHERE c1 IN (SELECT c3 FROM t2 WHERE c2 = fdt.c1 + 10) SELECT ... FROM fdt WHERE c1 BETWEEN (SELECT c3 FROM t2 WHERE c2 = fdt.c1 + 10) AND 100 SELECT ... FROM fdt WHERE EXISTS (SELECT c1 FROM t2 WHERE c2 > fdt.c1)
fdt â название ÑаблиÑÑ, поÑождÑнной в пÑедложении FROM. СÑÑоки, коÑоÑÑе не ÑооÑвеÑÑÑвÑÑÑ ÑÑÐ»Ð¾Ð²Ð¸Ñ WHERE, иÑклÑÑаÑÑÑÑ Ð¸Ð· fdt. ÐбÑаÑиÑе внимание, как в каÑеÑÑве вÑÑажений знаÑÐµÐ½Ð¸Ñ Ð¸ÑполÑзÑÑÑÑÑ ÑкалÑÑнÑе подзапÑоÑÑ. Ðак и лÑбÑе дÑÑгие запÑоÑÑ, подзапÑоÑÑ Ð¼Ð¾Ð³ÑÑ ÑодеÑжаÑÑ ÑложнÑе ÑаблиÑнÑе вÑÑажениÑ. ÐамеÑÑÑе Ñакже, ÑÑо fdt иÑполÑзÑеÑÑÑ Ð² подзапÑоÑаÑ
. Ðополнение имени c1 в виде fdt.c1 необÑ
одимо ÑолÑко, еÑли в поÑождÑнной ÑаблиÑе в подзапÑоÑе Ñакже оказÑваеÑÑÑ ÑÑÐ¾Ð»Ð±ÐµÑ c1. Ðолное Ð¸Ð¼Ñ Ð¿ÑидаÑÑ ÑÑноÑÑÑ Ð´Ð°Ð¶Ðµ Ñам, где без него можно обойÑиÑÑ. ÐÑÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ Ð¿Ð¾ÐºÐ°Ð·ÑваеÑ, как облаÑÑÑ Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ ÑÑолбÑов внеÑнего запÑоÑа ÑаÑпÑоÑÑÑанÑеÑÑÑ Ð½Ð° вÑе вложеннÑе в него внÑÑÑенние запÑоÑÑ.
7.2.3. ÐÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ GROUP BY и HAVING #
СÑÑоки поÑождÑнной вÑ
одной ÑаблиÑÑ, пÑоÑедÑие ÑилÑÑÑ WHERE, можно ÑгÑÑппиÑоваÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð¿ÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ GROUP BY, а заÑем оÑÑавиÑÑ Ð² ÑезÑлÑÑаÑе ÑолÑко нÑжнÑе гÑÑÐ¿Ð¿Ñ ÑÑÑок, иÑполÑзÑÑ Ð¿Ñедложение HAVING.
SELECTÑпиÑок_вÑбоÑкиFROM ... [WHERE ...] GROUP BYгÑÑппиÑÑÑÑий_ÑÑолбеÑ[,гÑÑппиÑÑÑÑий_ÑÑолбеÑ]...
ÐÑедложение GROUP BY гÑÑппиÑÑÐµÑ ÑÑÑоки ÑаблиÑÑ, обÑединÑÑ Ð¸Ñ
в Ð¾Ð´Ð½Ñ Ð³ÑÑÐ¿Ð¿Ñ Ð¿Ñи Ñовпадении знаÑений во вÑеÑ
пеÑеÑиÑленнÑÑ
ÑÑолбÑаÑ
. ÐоÑÑдок, в коÑоÑом ÑÐºÐ°Ð·Ð°Ð½Ñ ÑÑолбÑÑ, не Ð¸Ð¼ÐµÐµÑ Ð·Ð½Ð°ÑениÑ. Ð ÑезÑлÑÑаÑе набоÑÑ ÑÑÑок Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñми знаÑениÑми пÑеобÑазÑÑÑÑÑ Ð² оÑделÑнÑе ÑÑÑоки, пÑедÑÑавлÑÑÑие вÑе ÑÑÑоки гÑÑппÑ. ÐÑо Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾ Ð´Ð»Ñ ÑÑÑÑÐ°Ð½ÐµÐ½Ð¸Ñ Ð¸Ð·Ð±ÑÑоÑноÑÑи вÑÑ
однÑÑ
даннÑÑ
и/или Ð´Ð»Ñ Ð²ÑÑиÑÐ»ÐµÐ½Ð¸Ñ Ð°Ð³ÑегаÑнÑÑ
ÑÑнкÑий, пÑименÑннÑÑ
к ÑÑим гÑÑппам. ÐапÑимеÑ:
=>SELECT * FROM test1;x | y ---+--- a | 3 c | 2 b | 5 a | 1 (4 rows)=>SELECT x FROM test1 GROUP BY x;x --- a b c (3 rows)
Ðо вÑоÑом запÑоÑе Ð¼Ñ Ð½Ðµ могли напиÑаÑÑ SELECT * FROM test1 GROUP BY x, Ñак как Ð´Ð»Ñ ÑÑолбÑа y Ð½ÐµÑ ÐµÐ´Ð¸Ð½Ð¾Ð³Ð¾ знаÑениÑ, ÑвÑзанного Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ гÑÑппой. Ðднако ÑÑолбÑÑ, по коÑоÑÑм вÑполнÑеÑÑÑ Ð³ÑÑппиÑовка, можно иÑполÑзоваÑÑ Ð² ÑпиÑке вÑбоÑки, Ñак как они имеÑÑ ÐµÐ´Ð¸Ð½ÑÑвенное знаÑение в каждой гÑÑппе.
ÐообÑе говоÑÑ, в гÑÑппиÑованной ÑаблиÑе ÑÑолбÑÑ, не вклÑÑÑннÑе в ÑпиÑок GROUP BY, можно иÑполÑзоваÑÑ ÑолÑко в агÑегаÑнÑÑ
вÑÑажениÑÑ
. ÐÑÐ¸Ð¼ÐµÑ Ñакого агÑегаÑного вÑÑажениÑ:
=>SELECT x, sum(y) FROM test1 GROUP BY x;x | sum ---+----- a | 4 b | 5 c | 2 (3 rows)
ÐдеÑÑ sum â агÑегаÑÐ½Ð°Ñ ÑÑнкÑиÑ, вÑÑиÑлÑÑÑÐ°Ñ ÐµÐ´Ð¸Ð½ÑÑвенное знаÑение Ð´Ð»Ñ Ð²Ñей гÑÑппÑ. ÐодÑобнÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¾ ÑÑÑеÑÑвÑÑÑиÑ
агÑегаÑнÑÑ
ÑÑнкÑиÑÑ
можно найÑи в Разделе 9.21.
ÐодÑказка
ÐÑÑппиÑовка без агÑегаÑнÑÑ
вÑÑажений по ÑÑÑи вÑдаÑÑ Ð½Ð°Ð±Ð¾Ñ ÑазлиÑаÑÑиÑ
ÑÑ Ð·Ð½Ð°Ñений ÑÑолбÑов. ÐÑÐ¾Ñ Ð¶Ðµ ÑезÑлÑÑÐ°Ñ Ð¼Ð¾Ð¶Ð½Ð¾ полÑÑиÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð¿ÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ DISTINCT (Ñм. ÐодÑаздел 7.3.3).
ÐзглÑниÑе на ÑледÑÑÑий пÑимеÑ: в нÑм вÑÑиÑлÑеÑÑÑ Ð¾Ð±ÑÐ°Ñ ÑÑмма пÑодаж по ÐºÐ°Ð¶Ð´Ð¾Ð¼Ñ Ð¿ÑодÑкÑÑ (а не обÑÐ°Ñ ÑÑмма по вÑем пÑодÑкÑам):
SELECT product_id, p.name, (sum(s.units) * p.price) AS sales
FROM products p LEFT JOIN sales s USING (product_id)
GROUP BY product_id, p.name, p.price; Ð ÑÑом пÑимеÑе ÑÑолбÑÑ product_id, p.name и p.price Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿ÑиÑÑÑÑÑвоваÑÑ Ð² ÑпиÑке GROUP BY, Ñак как они иÑполÑзÑÑÑÑÑ Ð² ÑпиÑке вÑбоÑки. СÑÐ¾Ð»Ð±ÐµÑ s.units Ð¼Ð¾Ð¶ÐµÑ Ð¾ÑÑÑÑÑÑвоваÑÑ Ð² ÑпиÑке GROUP BY, Ñак как он иÑполÑзÑеÑÑÑ ÑолÑко в агÑегаÑном вÑÑажении (sum(...)), вÑÑиÑлÑÑÑем ÑÑÐ¼Ð¼Ñ Ð¿Ñодаж. ÐÐ»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ пÑодÑкÑа ÑÑÐ¾Ñ Ð·Ð°Ð¿ÑÐ¾Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÑ ÑÑÑÐ¾ÐºÑ Ñ Ð¸Ñоговой ÑÑммой по вÑем пÑодажам данного пÑодÑкÑа.
ÐÑли Ð±Ñ Ð² ÑаблиÑе products по ÑÑолбÑÑ product_id бÑл Ñоздан пеÑвиÑнÑй клÑÑ, Ñогда в данном пÑимеÑе бÑло Ð±Ñ Ð´Ð¾ÑÑаÑоÑно ÑгÑÑппиÑоваÑÑ ÑÑÑоки по product_id, Ñак как название и Ñена пÑодÑкÑа ÑÑнкÑионалÑно завиÑÑÑ Ð¾Ñ ÐºÐ¾Ð´Ð° пÑодÑкÑа и можно однознаÑно опÑеделиÑÑ, какое название и ÑÐµÐ½Ñ Ð²Ð¾Ð·Ð²ÑаÑаÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ гÑÑÐ¿Ð¿Ñ Ð¿Ð¾ ID.
Ð ÑÑандаÑÑе SQL GROUP BY Ð¼Ð¾Ð¶ÐµÑ Ð³ÑÑппиÑоваÑÑ ÑолÑко по ÑÑолбÑам иÑÑ
одной ÑаблиÑÑ, но ÑаÑÑиÑение Postgres Pro позволÑÐµÑ Ð¸ÑполÑзоваÑÑ Ð² GROUP BY ÑÑолбÑÑ Ð¸Ð· ÑпиÑка вÑбоÑки. Также возможна гÑÑппиÑовка по вÑÑажениÑм, а не пÑоÑÑо именам ÑÑолбÑов.
ÐÑли ÑаблиÑа бÑла ÑгÑÑппиÑована Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ GROUP BY, но инÑеÑÐµÑ Ð¿ÑедÑÑавлÑÑÑ ÑолÑко некоÑоÑÑе гÑÑппÑ, оÑÑилÑÑÑоваÑÑ Ð¸Ñ
можно Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð¿ÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ HAVING, дейÑÑвÑÑÑего подобно WHERE. ÐапиÑÑваеÑÑÑ ÑÑо Ñак:
SELECTÑпиÑок_вÑбоÑкиFROM ... [WHERE ...] GROUP BY ... HAVINGлогиÑеÑкое_вÑÑажение
РпÑедложении HAVING могÑÑ Ð¸ÑполÑзоваÑÑÑÑ Ð¸ гÑÑппиÑÑÑÑие вÑÑажениÑ, и вÑÑажениÑ, не ÑÑаÑÑвÑÑÑие в гÑÑппиÑовке (в ÑÑом ÑлÑÑае ÑÑо Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð°Ð³ÑегиÑÑÑÑие ÑÑнкÑии).
ÐÑимеÑ:
=>SELECT x, sum(y) FROM test1 GROUP BY x HAVING sum(y) > 3;x | sum ---+----- a | 4 b | 5 (2 rows)=>SELECT x, sum(y) FROM test1 GROUP BY x HAVING x < 'c';x | sum ---+----- a | 4 b | 5 (2 rows)
РеÑÑ Ð¾Ð´Ð¸Ð½ более ÑеалиÑÑиÑнÑй пÑимеÑ:
SELECT product_id, p.name, (sum(s.units) * (p.price - p.cost)) AS profit
FROM products p LEFT JOIN sales s USING (product_id)
WHERE s.date > CURRENT_DATE - INTERVAL '4 weeks'
GROUP BY product_id, p.name, p.price, p.cost
HAVING sum(p.price * s.units) > 5000; Рданном пÑимеÑе пÑедложение WHERE вÑбиÑÐ°ÐµÑ ÑÑÑоки по ÑÑолбÑÑ, не вклÑÑÑÐ½Ð½Ð¾Ð¼Ñ Ð² гÑÑппиÑÐ¾Ð²ÐºÑ (вÑÑажение иÑÑинно ÑолÑко Ð´Ð»Ñ Ð¿Ñодаж за поÑледние ÑеÑÑÑе недели), Ñогда как пÑедложение HAVING оÑÑилÑÑÑовÑÐ²Ð°ÐµÑ Ð³ÑÑÐ¿Ð¿Ñ Ñ Ð¾Ð±Ñей ÑÑммой пÑодаж болÑÑе 5000. ÐамеÑÑÑе, ÑÑо агÑегаÑнÑе вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð½Ðµ обÑзаÑелÑно Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñми во вÑеÑ
ÑаÑÑÑÑ
запÑоÑа.
ÐÑли в запÑоÑе еÑÑÑ Ð²ÑÐ·Ð¾Ð²Ñ Ð°Ð³ÑегаÑнÑÑ
ÑÑнкÑий, но Ð½ÐµÑ Ð¿ÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ GROUP BY, ÑÑÑоки вÑÑ Ñавно бÑдÑÑ Ð³ÑÑппиÑоваÑÑÑÑ: в ÑезÑлÑÑаÑе окажеÑÑÑ Ð¾Ð´Ð½Ð° ÑÑÑока гÑÑÐ¿Ð¿Ñ (или возможно, ни одной ÑÑÑоки, еÑли ÑÑа ÑÑÑока бÑÐ´ÐµÑ Ð¾ÑбÑоÑена пÑедложением HAVING). ÐÑо ÑпÑаведливо и Ð´Ð»Ñ Ð·Ð°Ð¿ÑоÑов, коÑоÑÑе ÑодеÑÐ¶Ð°Ñ ÑолÑко пÑедложение HAVING, но не ÑодеÑÐ¶Ð°Ñ Ð²ÑÐ·Ð¾Ð²Ñ Ð°Ð³ÑегаÑнÑÑ
ÑÑнкÑий и пÑедложение GROUP BY.
7.2.4. GROUPING SETS, CUBE и ROLLUP #
Ðолее ÑложнÑе, Ñем опиÑаннÑе вÑÑе, опеÑаÑии гÑÑппиÑовки Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ Ñ ÐºÐ¾Ð½ÑепÑией набоÑов гÑÑппиÑованиÑ. ÐаннÑе, вÑбÑаннÑе пÑедложениÑми FROM и WHERE, гÑÑппиÑÑÑÑÑÑ Ð¾ÑделÑно Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ заданного набоÑа гÑÑппиÑованиÑ, заÑем Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ гÑÑÐ¿Ð¿Ñ Ð²ÑÑиÑлÑÑÑÑÑ Ð°Ð³ÑегаÑнÑе ÑÑнкÑии как Ð´Ð»Ñ Ð¿ÑоÑÑÑÑ
пÑедложений GROUP BY, и в конÑе возвÑаÑаÑÑÑÑ ÑезÑлÑÑаÑÑ. ÐапÑимеÑ:
=>SELECT * FROM items_sold;brand | size | sales -------+------+------- Foo | L | 10 Foo | M | 20 Bar | M | 15 Bar | L | 5 (4 rows)=>SELECT brand, size, sum(sales) FROM items_sold GROUP BY GROUPING SETS ((brand), (size), ());brand | size | sum -------+------+----- Foo | | 30 Bar | | 20 | L | 15 | M | 35 | | 50 (5 rows)
Ркаждом внÑÑÑеннем ÑпиÑке GROUPING SETS могÑÑ Ð·Ð°Ð´Ð°Ð²Ð°ÑÑÑÑ Ð½Ð¾Ð»Ñ Ð¸Ð»Ð¸ более ÑÑолбÑов или вÑÑажений, коÑоÑÑе воÑпÑинимаÑÑÑÑ Ñак же, как еÑли Ð±Ñ Ð¾Ð½Ð¸ бÑли непоÑÑедÑÑвенно запиÑÐ°Ð½Ñ Ð² пÑедложении GROUP BY. ÐÑÑÑой Ð½Ð°Ð±Ð¾Ñ Ð³ÑÑппиÑовки ознаÑаеÑ, ÑÑо вÑе ÑÑÑоки ÑводÑÑÑÑ Ðº одной гÑÑппе (коÑоÑÐ°Ñ Ð²ÑводиÑÑÑ, даже еÑли вÑ
однÑÑ
ÑÑÑок неÑ), как опиÑано вÑÑе Ð´Ð»Ñ Ð°Ð³ÑегаÑнÑÑ
ÑÑнкÑий без пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ GROUP BY.
СÑÑлки на гÑÑппиÑÑÑÑие ÑÑолбÑÑ Ð¸Ð»Ð¸ вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð·Ð°Ð¼ÐµÐ½ÑÑÑÑÑ Ð² ÑезÑлÑÑиÑÑÑÑÐ¸Ñ ÑÑÑÐ¾ÐºÐ°Ñ Ð·Ð½Ð°ÑениÑми NULL Ð´Ð»Ñ ÑÐµÑ Ð³ÑÑппиÑÑÑÑÐ¸Ñ Ð½Ð°Ð±Ð¾Ñов, в коÑоÑÑÑ ÑÑи ÑÑолбÑÑ Ð¾ÑÑÑÑÑÑвÑÑÑ. ЧÑÐ¾Ð±Ñ Ð¼Ð¾Ð¶Ð½Ð¾ бÑло понÑÑÑ, ÑезÑлÑÑаÑом какого гÑÑппиÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÑÑала конкÑеÑÐ½Ð°Ñ Ð²ÑÑ Ð¾Ð´Ð½Ð°Ñ ÑÑÑока, пÑедназнаÑена ÑÑнкÑиÑ, опиÑÐ°Ð½Ð½Ð°Ñ Ð² ТаблиÑе 9.64.
ÐÐ»Ñ ÑÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð´Ð²ÑÑ ÑаÑпÑоÑÑÑанÑннÑÑ Ð²Ð¸Ð´Ð¾Ð² набоÑов гÑÑппиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¿ÑедÑÑмоÑÑена кÑаÑÐºÐ°Ñ Ð·Ð°Ð¿Ð¸ÑÑ. ÐÑедложение ÑоÑмÑ
ROLLUP (e1,e2,e3, ... )
пÑедÑÑавлÑÐµÑ Ð·Ð°Ð´Ð°Ð½Ð½Ñй ÑпиÑок вÑÑажений и вÑÐµÑ Ð¿ÑеÑикÑов ÑпиÑка, вклÑÑÐ°Ñ Ð¿ÑÑÑой ÑпиÑок; Ñо еÑÑÑ Ð¾Ð½Ð¾ ÑавнознаÑно запиÑи
GROUPING SETS (
( e1, e2, e3, ... ),
...
( e1, e2 ),
( e1 ),
( )
)Ðно ÑаÑÑо пÑименÑеÑÑÑ Ð´Ð»Ñ Ð°Ð½Ð°Ð»Ð¸Ð·Ð° иеÑаÑÑ Ð¸ÑеÑÐºÐ¸Ñ Ð´Ð°Ð½Ð½ÑÑ , напÑимеÑ, Ð´Ð»Ñ ÑÑммиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð·Ð°ÑплаÑÑ Ð¿Ð¾ оÑделам, подÑазделениÑм и компании в Ñелом.
ÐÑедложение ÑоÑмÑ
CUBE (e1,e2, ... )
пÑедÑÑавлÑÐµÑ Ð·Ð°Ð´Ð°Ð½Ð½Ñй ÑпиÑок и вÑе его возможнÑе подмножеÑÑва (ÑÑÐµÐ¿ÐµÐ½Ñ Ð¼Ð½Ð¾Ð¶ÐµÑÑва). Таким обÑазом, запиÑÑ
CUBE ( a, b, c )
ÑавнознаÑна
GROUPING SETS (
( a, b, c ),
( a, b ),
( a, c ),
( a ),
( b, c ),
( b ),
( c ),
( )
)ÐлеменÑами пÑедложений CUBE и ROLLUP могÑÑ Ð±ÑÑÑ Ð»Ð¸Ð±Ð¾ оÑделÑнÑе вÑÑажениÑ, либо вложеннÑе ÑпиÑки ÑлеменÑов в ÑкобкаÑ
. ÐложеннÑе ÑпиÑки обÑабаÑÑваÑÑÑÑ ÐºÐ°Ðº аÑомаÑнÑе единиÑÑ, Ñ ÐºÐ¾ÑоÑÑми ÑоÑмиÑÑÑÑÑÑ Ð¾ÑделÑнÑе набоÑÑ Ð³ÑÑппиÑованиÑ. ÐапÑимеÑ:
CUBE ( (a, b), (c, d) )
ÑавнознаÑно
GROUPING SETS (
( a, b, c, d ),
( a, b ),
( c, d ),
( )
)и
ROLLUP ( a, (b, c), d )
ÑавнознаÑно
GROUPING SETS (
( a, b, c, d ),
( a, b, c ),
( a ),
( )
)ÐонÑÑÑÑкÑии CUBE и ROLLUP могÑÑ Ð¿ÑименÑÑÑÑÑ Ð»Ð¸Ð±Ð¾ непоÑÑедÑÑвенно в пÑедложении GROUP BY, либо вкладÑваÑÑÑÑ Ð²Ð½ÑÑÑÑ Ð¿ÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ GROUPING SETS. ÐÑли одно пÑедложение GROUPING SETS вкладÑваеÑÑÑ Ð²Ð½ÑÑÑÑ Ð´ÑÑгого, ÑезÑлÑÑÐ°Ñ Ð±ÑÐ´ÐµÑ Ñаким же, как еÑли Ð±Ñ Ð²Ñе ÑлеменÑÑ Ð²Ð½ÑÑÑеннего пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð±Ñли запиÑÐ°Ð½Ñ Ð½ÐµÐ¿Ð¾ÑÑедÑÑвенно во внеÑнем.
ÐÑли в одном пÑедложении GROUP BY задаÑÑÑÑ Ð½ÐµÑколÑко ÑлеменÑов гÑÑппиÑованиÑ, оконÑаÑелÑнÑй ÑпиÑок набоÑов гÑÑппиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð±ÑазÑеÑÑÑ ÐºÐ°Ðº пÑÑмое пÑоизведение ÑÑиÑ
ÑлеменÑов. ÐапÑимеÑ:
GROUP BY a, CUBE (b, c), GROUPING SETS ((d), (e))
ÑавнознаÑно
GROUP BY GROUPING SETS (
(a, b, c, d), (a, b, c, e),
(a, b, d), (a, b, e),
(a, c, d), (a, c, e),
(a, d), (a, e)
)ÐÑли задаÑÑÑÑ Ð½ÐµÑколÑко ÑлеменÑов гÑÑппиÑованиÑ, оконÑаÑелÑнÑй ÑпиÑок набоÑов гÑÑппиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ ÑодеÑжаÑÑ Ð´ÑблиÑÑÑÑиеÑÑ ÑезÑлÑÑаÑÑ. ÐапÑимеÑ:
GROUP BY ROLLUP (a, b), ROLLUP (a, c)
ÑавнознаÑно
GROUP BY GROUPING SETS (
(a, b, c),
(a, b),
(a, b),
(a, c),
(a),
(a),
(a, c),
(a),
()
) ÐÑли ÑÑи дÑблиÑÑÑÑиеÑÑ ÑезÑлÑÑаÑÑ Ð½ÐµÐ¶ÐµÐ»Ð°ÑелÑнÑ, иÑ
можно ÑбÑаÑÑ, добавив DISTINCT непоÑÑедÑÑвенно в пÑедложение GROUP BY. Таким обÑазом:
GROUP BY DISTINCT ROLLUP (a, b), ROLLUP (a, c)ÑавнознаÑно
GROUP BY GROUPING SETS (
(a, b, c),
(a, b),
(a, c),
(a),
()
) ÐÑо не Ñо же Ñамое, ÑÑо SELECT DISTINCT, поÑколÑÐºÑ ÑезÑлÑÑиÑÑÑÑие ÑÑÑоки вÑÑ Ð¶Ðµ могÑÑ ÑодеÑжаÑÑ Ð´ÑблиÑÑÑÑиеÑÑ Ð·Ð°Ð¿Ð¸Ñи. ÐÑли лÑбой из ÑÑолбÑов, не ÑÑаÑÑвÑÑÑиÑ
в гÑÑппиÑовании, ÑодеÑÐ¶Ð¸Ñ Ð·Ð½Ð°Ñение NULL, в ÑезÑлÑÑаÑе оно не бÑÐ´ÐµÑ Ð¾ÑлиÑаÑÑÑÑ Ð¾Ñ NULL, полÑÑенного пÑи гÑÑппиÑовании ÑÑого ÑÑолбÑа.
ÐÑимеÑание
ÐонÑÑÑÑкÑÐ¸Ñ (a, b) обÑÑно воÑпÑинимаеÑÑÑ Ð² вÑÑажениÑÑ
как конÑÑÑÑкÑÐ¾Ñ ÑÑÑоки. Ðднако в пÑедложении GROUP BY на веÑÑ
нем ÑÑовне вÑÑажений запиÑÑ (a, b) воÑпÑинимаеÑÑÑ ÐºÐ°Ðº ÑпиÑок вÑÑажений, как опиÑано вÑÑе. ÐÑли вам по какой-либо пÑиÑине нÑжен именно конÑÑÑÑкÑÐ¾Ñ ÑÑÑоки в вÑÑажении гÑÑппиÑованиÑ, иÑполÑзÑйÑе запиÑÑ ROW(a, b).
7.2.5. ÐбÑабоÑка оконнÑÑ ÑÑнкÑий #
ÐÑли запÑÐ¾Ñ ÑодеÑÐ¶Ð¸Ñ Ð¾ÐºÐ¾Ð½Ð½Ñе ÑÑнкÑии (Ñм. Раздел 3.5, Раздел 9.22 и ÐодÑаздел 4.2.8), ÑÑи ÑÑнкÑии вÑÑиÑлÑÑÑÑÑ Ð¿Ð¾Ñле каждой гÑÑппиÑовки, агÑегаÑнÑÑ
вÑÑажений и ÑилÑÑÑаÑии HAVING. ÐÑÑгими Ñловами, еÑли в запÑоÑе еÑÑÑ Ð°Ð³ÑегаÑнÑе ÑÑнкÑии, пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ GROUP BY или HAVING, оконнÑе ÑÑнкÑии видÑÑ Ð½Ðµ иÑÑ
однÑе ÑÑÑоки, полÑÑеннÑе из FROM/WHERE, а ÑгÑÑппиÑованнÑе.
Ðогда иÑполÑзÑÑÑÑÑ Ð½ÐµÑколÑко оконнÑÑ
ÑÑнкÑий, вÑе оконнÑе ÑÑнкÑии, имеÑÑие в ÑвоиÑ
опÑеделениÑÑ
ÑавнознаÑнÑе пÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ PARTITION BY и ORDER BY, гаÑанÑиÑованно видÑÑ Ð¾Ð´Ð¸Ð½ поÑÑдок ÑоÑÑиÑовки вÑ
однÑÑ
ÑÑÑок, даже еÑли ORDER BY не опÑеделÑÐµÑ ÑÑÐ¾Ñ Ð¿Ð¾ÑÑдок однознаÑно. Ðднако оÑноÑиÑелÑно ÑÑнкÑий Ñ ÑазнÑми ÑоÑмÑлиÑовками PARTITION BY и ORDER BY никакиÑ
гаÑанÑий не даÑÑÑÑ. (Ð ÑакиÑ
ÑлÑÑаÑÑ
Ð¼ÐµÐ¶Ð´Ñ Ð¿ÑоÑ
одами вÑÑиÑлений оконнÑÑ
ÑÑнкÑий обÑÑно ÑÑебÑеÑÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑй ÑÑап ÑоÑÑиÑовки и ÑÑа ÑоÑÑиÑовка Ð¼Ð¾Ð¶ÐµÑ Ð½Ðµ ÑоÑ
ÑанÑÑÑ Ð¿Ð¾ÑÑдок ÑÑÑок, ÑавнознаÑнÑй Ñ ÑоÑки зÑÐµÐ½Ð¸Ñ ORDER BY.)
РнаÑÑоÑÑее вÑÐµÐ¼Ñ Ð¾ÐºÐ¾Ð½Ð½Ñе ÑÑнкÑии вÑегда ÑÑебÑÑÑ Ð¿ÑедваÑиÑелÑно оÑÑоÑÑиÑованнÑÑ
даннÑÑ
, Ñак ÑÑо ÑезÑлÑÑÐ°Ñ Ð·Ð°Ð¿ÑоÑа бÑÐ´ÐµÑ Ð¾ÑÑоÑÑиÑован ÑоглаÑно ÑÐ¾Ð¼Ñ Ð¸Ð»Ð¸ Ð¸Ð½Ð¾Ð¼Ñ Ð¿ÑÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ PARTITION BY/ORDER BY оконнÑÑ
ÑÑнкÑий. Ðднако полагаÑÑÑÑ Ð½Ð° ÑÑо не ÑледÑеÑ. ÐÑли Ð²Ñ Ñ
оÑиÑе, ÑÑÐ¾Ð±Ñ ÑезÑлÑÑаÑÑ ÑоÑÑиÑовалиÑÑ Ð¾Ð¿ÑеделÑннÑм обÑазом, Ñвно добавÑÑе пÑедложение ORDER BY на веÑÑ
нем ÑÑовне запÑоÑа.