簡體   English   中英

來自數組的不同值?

[英]Distinct values from an array?

下表:

CREATE TEMPORARY TABLE guys ( guy_id integer primary key, guy text );
CREATE TEMPORARY TABLE sales ( log_date date, sales_guys integer[], sales smallint );
INSERT INTO guys VALUES(1,'john'),(2,'joe');
INSERT INTO sales VALUES('2016-01-01', '{1,2}', 2),('2016-01-02','{1,2}',4);

以下查詢非常適合顯示給定日期的名稱:

SELECT log_date, sales_guys, ARRAY_AGG(guy), sales 
FROM sales 
JOIN guys ON 
   guys.guy_id = ANY(sales.sales_guys) 
GROUP BY log_date, sales_guys, sales 
ORDER BY log_date ASC;

  log_date  | sales_guys | array_agg  | sales 
------------+------------+------------+-------
 2016-01-01 | {1,2}      | {john,joe} |     2
 2016-01-02 | {1,2}      | {john,joe} |     4

以下查詢有問題地給我每個人每個日期的名字,因此這里每個名字兩次,依此類推):

SELECT sales_guys, ARRAY_AGG(guy), SUM(sales) AS sales
FROM sales
JOIN guys ON guys.guy_id = ANY(sales.sales_guys)
GROUP BY sales_guys;

產量:

 sales_guys |      array_agg      | sales 
------------+---------------------+-------
 {1,2}      | {john,joe,john,joe} |    12

有什么方法可以減少ARRAY_AGG調用以僅給出唯一名稱嗎?

您可以在聚合內使用DISTINCT

SELECT sales_guys, ARRAY_AGG(DISTINCT guy), SUM(sales) AS sales FROM sales JOIN guys ON guys.guy_id = ANY(sales.sales_guys) GROUP BY sales_guys;

沒有ORDER BY您無法信任任何ORDER BY 除了數組元素在未嵌套時按數組順序排列。 但是,如果查詢對結果的影響更大,則可能會對其進行重新排序。

您只需將ORDER BY添加到Postgres中的任何聚合函數中:

SELECT s.sales_guys, ARRAY_AGG(DISTINCT g.guy ORDER BY g.guy) AS names, SUM(s.sales) AS sum_sales
FROM   sales s
JOIN   guys  g ON g.guy_id = ANY(s.sales_guys)
GROUP  BY s.sales_guys;

但這顯然不是數組元素的原始順序。 而且查詢還有其他問題... IN= ANY()都不關心右側集合,列表或數組中元素的順序:

正確的解決方案

對於此任務(請注意細節!):

獲取每個數組sales_guys的總sales ,其中元素的順序有所不同(數組'{1,2}''{2,1}'不相同),而sales_guys既沒有重復元素也沒有NULL。 按匹配順序添加解析名稱數組。

unnest()WITH ORDINALITY一起WITH ORDINALITY 解析名稱之前聚合數組,這樣更便宜且更不易出錯。

SELECT s.*, g.
FROM  (
   SELECT sales_guys, sum (sales) AS total_sales                -- aggregate first in subquery
   FROM   sales
   GROUP  BY 1
   ) s
, LATERAL (
   SELECT array_agg(guy ORDER BY ord) AS names                  -- order by original order
   FROM   unnest(s.sales_guys) WITH ORDINALITY sg(guy_id, ord)  -- with order of elements
   LEFT   JOIN guys g USING (guy_id)                            -- LEFT JOIN to add NULL for missing guy_id
   ) g;

可以使用無條件CROSS JOIN LATERAL子查詢-逗號( , )是速記符號-因為子查詢中的聚合保證每一行都有結果。 否則,您將使用LEFT JOIN LATERAL .. ON true

詳細說明:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM