使用PostgreSQL 8.4,我已經成功地能夠使用ARRAY_AGG()取多個訂單的情況下,讓每個客戶單行:如何通過array_agg遍歷迭代列?
從這:
order_id|customer_id|order_date |order_desc
1 |1 |"2010-01-01"|"Tom's First"
2 |1 |"2010-04-01"|"Tom's Second"
7 |1 |"2010-04-13"|"Tom's Third"
8 |1 |"2011-04-13"|"Tom's Last"
5 |1 |"2011-06-20"|"Tom's Really Last."
3 |2 |"2010-07-07"|"Dick's First"
6 |2 |"2011-07-07"|"Dick's Other"
4 |3 |"2011-04-04"|"Harry's Only"
使用此:
select cu.customer, array_agg(ord.order_id) as orders from test_order ord
inner join test_customer cu
on ord.customer_id = cu.customer_id
group by cu.customer
結果:
customer |orders
"Tom" |"{1,2,7,8,5}"
"Dick" |"{3,6}"
"Harry" |"{4}"
的d我可以抓住陣列片創建新列,如果我硬代碼每個迭代:
select cu.customer,
(array_agg(ord.order_id))[1] as order_1,
(array_agg(ord.order_id))[2] as order_2,
(array_agg(ord.order_id))[3] as order_3,
(array_agg(ord.order_id))[4] as order_4,
(array_agg(ord.order_id))[5] as order_5
from test_order ord
inner join test_customer cu
on ord.customer_id = cu.customer_id
group by cu.customer
結果:
customer|order_1|order_2|order_3|order_4|order_5
"Dick" |3 |6 | | |
"Harry" |4 | | | |
"Tom" |8 |1 |5 |2 |7
然而,想什麼,我做的,在兩個步驟:
For循環我的方式通過記錄,以便我不必創建該字段的每個迭代。好消息是上面的結構沒有錯誤,只是傳遞NULL,但是如果我遇到了一些瘋狂的記錄,我不必在我的聲明中手動創建order_55,order_56等。
更妙的是最終沒有通過其特定的領域,有它在所有的領域進行迭代(除非該CUSTOMER_ID),給我的每場的迭代,該效果:
customer|order_id1|order_date1|order_desc1|order_id2|order_date2|order_desc2| ...
等等基本上加入父表(客戶)的子(訂單),但有多個子記錄跨越一行而不是創建倍數。
(是的,我知道這與您爲什麼首先執行父/子表的基本概念相反,不過,我將此傳遞給客戶端,這將使該過程變得更加容易。)
更新:我已經得到了與拆解功能更接近......我第一次稱呼它,它創建的列和填充的客戶之一。但由於某些原因,我的IF NOT EXISTS在單獨運行時工作,但不在函數內:我得到「column order_id1 exists」錯誤。我也想最終修改這個,以便特定的字段不被硬編碼;而不是customer_id我想要做一些事情,比如傳遞父表,子表和連接ID,並且用這種交叉表方式完全追加子表。
CREATE FUNCTION loop_test(integer) RETURNS integer AS $$
DECLARE
rOrder RECORD;
loop_counter INT := 1;
target_customer_id ALIAS FOR $1;
BEGIN
FOR rOrder IN SELECT *
FROM vdad_data.test_order
WHERE customer_id = target_customer_id
ORDER BY order_id LOOP
IF NOT EXISTS
(
SELECT * FROM information_schema.COLUMNS
WHERE COLUMN_NAME= 'order_id' || loop_counter
AND TABLE_NAME='test_customer'
AND TABLE_SCHEMA='vdad_data'
)
THEN
EXECUTE 'ALTER TABLE vdad_data.test_customer
ADD COLUMN order_id' || loop_counter || ' integer';
END IF;
IF NOT EXISTS
(
SELECT * FROM information_schema.COLUMNS
WHERE COLUMN_NAME= 'order_date' || loop_counter
AND TABLE_NAME='test_customer'
AND TABLE_SCHEMA='vdad_data'
)
THEN
EXECUTE 'ALTER TABLE vdad_data.test_customer
ADD COLUMN order_date' || loop_counter || ' date';
END IF;
IF NOT EXISTS
(
SELECT * FROM information_schema.COLUMNS
WHERE COLUMN_NAME= 'order_desc' || loop_counter
AND TABLE_NAME='test_customer'
AND TABLE_SCHEMA='vdad_data'
)
THEN
EXECUTE 'ALTER TABLE vdad_data.test_customer
ADD COLUMN order_desc' || loop_counter || ' character varying';
END IF;
EXECUTE 'UPDATE vdad_data.test_customer
SET order_id' || loop_counter || ' = ' || rOrder.order_id ||',
order_date' || loop_counter || ' = ' || quote_literal(to_char(rOrder.order_date,'yyyy-mm-dd')) ||',
order_desc' || loop_counter || ' = ' || quote_literal(rOrder.order_desc) ||'
WHERE customer_id = ' ||rOrder.customer_id;
loop_counter = loop_counter + 1;
END LOOP;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
我爲是所有在地圖上道歉,因爲我一直在嘗試了一次,我不能完全得到解決這個幾件事情。任何幫助表示讚賞,謝謝!
您是否想要做一些類似[this crosstab](http://www.postgresql.org/docs/current/static/tablefunc.html#AEN126191)的函數? –
人。有點。我猜這是一個9.0的功能,因爲我沒有在8.4。但似乎仍然需要每個領域的手動硬編碼?並且每個數據字段的標題不是由第三列(該示例中的「cat」值)確定的,它只是現有列標題的迭代:order_id變爲order_id1,order_id2等。 – MitchO
@MitchO:它也在8.4。您需要安裝contrib。 –