2

我有一张这样的桌子:

SELECT * FROM orders;

 client_id | order_id | salesman_id | price
-----------+----------+-------------+-------
         1 |      167 |           1 |    65
         1 |      367 |           1 |    27
         2 |      401 |           1 |    29
         2 |      490 |           2 |    48
         3 |      199 |           1 |    68
         3 |      336 |           2 |    22
         3 |      443 |           1 |    84
         3 |      460 |           2 |    92

我想为每个独特的推销员和客户对的每个最高价格的销售找到一个 order_ids 数组。在这种情况下,我想要结果表:

 salesman_id |   order_id
-------------+----------------
           1 | {167, 401, 443}
           2 | {490, 460}

到目前为止,我有一个查询大纲:

SELECT salesman_id, max_client_salesman(order_id)
FROM orders
GROUP BY salesman_id;

但是我在编写聚合函数max_client_salesman 时遇到了麻烦。

postgres 中聚合函数和数组的在线文档非常少。任何帮助表示赞赏。

4

2 回答 2

2

标准 SQL

我会结合窗口函数last_value()firstvalue()withDISTINCT以有效地获取价格最高的订单,(salesman_id, client_id)然后使用简单的聚合函数array_agg()将其聚合到您要查找的数组中。

SELECT salesman_id
      ,array_agg(max_order_id) AS most_expensive_orders_per_client
FROM  (
   SELECT DISTINCT
          salesman_id, client_id
         ,last_value(order_id) OVER (PARTITION BY salesman_id, client_id
                                     ORDER BY price
                                     ROWS BETWEEN UNBOUNDED PRECEDING
                                     AND UNBOUNDED FOLLOWING) AS max_order_id
   FROM   orders
   ) x
GROUP  BY salesman_id
ORDER  BY salesman_id;

回报:

 salesman_id |  most_expensive_orders_per_client
-------------+------------------------------------
           1 | {167, 401, 443}
           2 | {490, 460}

SQL小提琴。

如果每个 有多个最高价格(salesman_id, client_id),则此查询仅任意选择一个 order_id- 因为缺乏定义。

对于此解决方案,必须了解之前应用了窗口函数DISTINCT。如何DISTINCT与窗口函数结合:

有关解释,ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING请参阅dba.SE 上密切相关的答案

非标更简单DISTINCT ON

作为 SQL 标准的扩展,PostgreSQL 实现了DISTINCT ON. 有了它,您可以非常有效地根据一组定义的列选择唯一的行。
它不会比这更简单或更快:

SELECT salesman_id
      ,array_agg(order_id) AS most_expensive_orders_per_client
FROM  (
   SELECT DISTINCT ON (1, client_id)
          salesman_id, order_id
   FROM   orders
   ORDER  BY salesman_id, client_id, price DESC
   ) x
GROUP  BY 1
ORDER  BY 1;

SQL小提琴。

我还使用位置参数来缩短语法。细节:

于 2013-02-06T02:28:08.380 回答
0

我认为您希望将 Postgres 函数array_aggrow_number() 但是,您对查询的描述对我来说没有意义。

以下获取客户和销售人员以及销售人员的最高价格订单的订单列表:

select client_id, salesman_id, array_agg(order_id)
from (select o.*,
             row_number() over (partition by salesman_id order by price desc) as sseqnum,
             row_number() over (partition by client_id order by price desc) as cseqnum
      from orders o
     ) o
where sseqnum = 1
group by salesman_id, client_id

我不知道您所说的“每个销售人员和客户的最高价格销售”是什么意思。也许你想要:

where sseqnum = 1 or cseqnum = 1
于 2013-02-06T00:28:01.820 回答