F.24. intagg
ÐодÑÐ»Ñ intagg пÑедоÑÑавлÑÐµÑ Ð°Ð³ÑегаÑÐ¾Ñ Ð¸ нÑмеÑаÑÐ¾Ñ ÑелÑÑ
ÑиÑел. Ðа даннÑй Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð¸Ð¼ÐµÑÑÑÑ Ð²ÑÑÑоеннÑе ÑÑнкÑии, пÑедлагаÑÑие более ÑиÑокие возможноÑÑи, поÑÑÐ¾Ð¼Ñ intagg ÑÑиÑаеÑÑÑ ÑÑÑаÑевÑим. Ðднако ÑÑÐ¾Ñ Ð¼Ð¾Ð´ÑÐ»Ñ Ð¿ÑÐ¾Ð´Ð¾Ð»Ð¶Ð°ÐµÑ ÑÑÑеÑÑвоваÑÑ Ð´Ð»Ñ Ð¾Ð±ÑаÑной ÑовмеÑÑимоÑÑи, ÑепеÑÑ ÐºÐ°Ðº Ð½Ð°Ð±Ð¾Ñ Ð¾Ð±ÑÑÑок вÑÑÑоеннÑÑ
ÑÑнкÑий.
F.24.1. ФÑнкÑии
ÐгÑегаÑÐ¾Ñ ÑеализÑеÑÑÑ ÑÑнкÑией int_array_aggregate(integer), коÑоÑÐ°Ñ Ð²ÑдаÑÑ Ð¼Ð°ÑÑив ÑелÑÑ
ÑиÑел, ÑодеÑжаÑий в ÑоÑноÑÑи Ñе ÑиÑла, ÑÑо пеÑÐµÐ´Ð°Ð½Ñ ÐµÐ¹. ÐÑо обÑÑÑка вÑÑÑоенной ÑÑнкÑии array_agg, коÑоÑÐ°Ñ Ð´ÐµÐ»Ð°ÐµÑ Ñо же Ñамое Ð´Ð»Ñ Ð¼Ð°ÑÑива лÑбого Ñипа.
ÐÑмеÑаÑÐ¾Ñ ÑеализÑеÑÑÑ ÑÑнкÑией int_array_enum(integer[]), коÑоÑÐ°Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÑ Ð½Ð°Ð±Ð¾Ñ ÑелÑÑ
(setof integer). Ðо ÑÑÑи его дейÑÑвие обÑаÑно дейÑÑвие агÑегаÑоÑа: полÑÑив маÑÑив ÑелÑÑ
, он ÑазвоÑаÑÐ¸Ð²Ð°ÐµÑ ÐµÐ³Ð¾ в Ð½Ð°Ð±Ð¾Ñ ÑÑÑок. ÐÑо оболоÑка ÑÑнкÑии unnest, коÑоÑÐ°Ñ Ð´ÐµÐ»Ð°ÐµÑ Ñо же Ñамое Ð´Ð»Ñ Ð¼Ð°ÑÑива лÑбого Ñипа.
F.24.2. ÐÑимеÑÑ Ð¸ÑполÑзованиÑ
Ðо Ð¼Ð½Ð¾Ð³Ð¸Ñ Ð¡Ð£ÐРеÑÑÑ Ð¿Ð¾Ð½ÑÑие ÑаблиÑÑ ÑооÑноÑений «один ко многим». Ð¢Ð°ÐºÐ°Ñ ÑаблиÑа обÑÑно Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð¼ÐµÐ¶Ð´Ñ Ð´Ð²ÑÐ¼Ñ Ð¸Ð½Ð´ÐµÐºÑиÑованнÑми ÑаблиÑами, напÑимеÑ:
CREATE TABLE left (id INT PRIMARY KEY, ...); CREATE TABLE right (id INT PRIMARY KEY, ...); CREATE TABLE one_to_many(left INT REFERENCES left, right INT REFERENCES right);
Ðак пÑавило, она иÑполÑзÑеÑÑÑ Ñак:
SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right)
WHERE one_to_many.left = item;ÐÑÐ¾Ñ Ð·Ð°Ð¿ÑÐ¾Ñ Ð²ÐµÑнÑÑ Ð²Ñе ÑлеменÑÑ Ð¸Ð· ÑаблиÑÑ ÑпÑава Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи в ÑаблиÑе Ñлева. ÐÑо оÑÐµÐ½Ñ ÑаÑпÑоÑÑÑанÑÐ½Ð½Ð°Ñ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¸Ñ Ð² SQL.
Ðднако ÑÑÐ¾Ñ Ð¿Ð¾Ð´Ñ
од Ð¼Ð¾Ð¶ÐµÑ Ð²ÑзÑваÑÑ Ð·Ð°ÑÑÑÐ´Ð½ÐµÐ½Ð¸Ñ Ñ Ð¾ÑÐµÐ½Ñ Ð±Ð¾Ð»ÑÑим колиÑеÑÑвом запиÑей в ÑаблиÑе one_to_many. ЧаÑÑо Ñакое Ñоединение влеÑÑÑ ÑканиÑование индекÑа и вÑбоÑÐºÑ ÐºÐ°Ð¶Ð´Ð¾Ð¹ запиÑи в ÑаблиÑе ÑпÑава Ð´Ð»Ñ ÐºÐ¾Ð½ÐºÑеÑного ÑлеменÑа Ñлева. ÐÑли Ñ Ð²Ð°Ñ Ð´Ð¸Ð½Ð°Ð¼Ð¸ÑеÑÐºÐ°Ñ ÑиÑÑема, Ñ ÑÑим ниÑего не поделаÑÑ. Ðо еÑли какое-Ñо множеÑÑво даннÑÑ
доволÑно ÑÑаÑиÑеÑкое, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе ÑоздаÑÑ ÑводнÑÑ ÑаблиÑÑ, пÑименив агÑегаÑоÑ.
CREATE TABLE summary AS SELECT left, int_array_aggregate(right) AS right FROM one_to_many GROUP BY left;
ÐÑа команда ÑоздаÑÑ ÑаблиÑÑ, ÑодеÑжаÑÑÑ Ð¾Ð´Ð½Ñ ÑÑÑÐ¾ÐºÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑлеменÑа Ñлева Ñ Ð¼Ð°ÑÑивом ÑлеменÑов ÑпÑава. Ðна малополезна, пока не найден Ð¿Ð¾Ð´Ñ Ð¾Ð´ÑÑий ÑпоÑоб иÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑÑого маÑÑива; именно Ð´Ð»Ñ ÑÑого и нÑжен нÑмеÑаÑÐ¾Ñ Ð¼Ð°ÑÑива. ÐÑ Ð¼Ð¾Ð¶ÐµÑе вÑполниÑÑ:
SELECT left, int_array_enum(right) FROM summary WHERE left = ÑлеменÑ; ÐÑиведÑннÑй вÑÑе запÑÐ¾Ñ Ñ Ð²Ñзовом int_array_enum вÑдаÑÑ Ñе же ÑезÑлÑÑаÑÑ, ÑÑо и
SELECT left, right FROM one_to_many WHERE left = ÑлеменÑ; ÐÑлиÑие ÑоÑÑÐ¾Ð¸Ñ Ð² Ñом, ÑÑо запÑÐ¾Ñ Ðº Ñводной ÑаблиÑе должен вÑдаÑÑ ÑолÑко Ð¾Ð´Ð½Ñ ÑÑÑÐ¾ÐºÑ ÑаблиÑÑ, Ñогда как непоÑÑедÑÑвеннÑй запÑÐ¾Ñ Ðº one_to_many поÑÑебÑÐµÑ ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа и вÑбоÑки ÑÑÑоки Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ запиÑи.
Ðа ÑеÑÑовом компÑÑÑеÑе команда EXPLAIN показала, ÑÑо ÑÑоимоÑÑÑ Ð·Ð°Ð¿ÑоÑа ÑнизилаÑÑ Ñ 8488 до 329. ÐÑÑ
однÑй запÑÐ¾Ñ Ð²ÑполнÑл Ñоединение Ñ ÑаблиÑей one_to_many и бÑл заменÑн на:
SELECT right, count(right) FROM
( SELECT left, int_array_enum(right) AS right
FROM summary JOIN (SELECT left FROM left_table WHERE left = ÑлеменÑ) AS lefts
ON (summary.left = lefts.left)
) AS list
GROUP BY right
ORDER BY count DESC;