如何提取 postgresql 中 ~120k 行总和的最大值?
How to extract the max of the sum of ~120k rows in postgresql?
我有一个自行车商店的数据库,table 我打电话给
"SalesOrderHeader"
其中包括以下 2 列:CustomerID
、TotalDue
。
它包含有关自行车商店所有销售的信息。所以如果f.e。一个顾客在商店里总共买了 2 次,他的 CustomerID
会有 2 个记录,每次他支付的金额 (TotalDue
)。
如何编写一个 select 查询来显示支付总额最高的 1 个(或多个,如果是平局)客户。结果必须显示 2 列,一列带有 CustomerID
,一列带有 TotalMoneyHePaid
。
您可以在 HAVING 子句中使用子查询来获取:
SELECT customerid,
sum(totaldue)
FROM SalesOrderHeader
GROUP BY customerid
HAVING sum(totaldue) = (
SELECT sum(totaldue)
FROM SalesOrderHeader
GROUP BY customerID
ORDER BY sum(totalDue) DESC LIMIT 1
)
子查询:
SELECT sum(totaldue)
FROM SalesOrderHeader
GROUP BY customerID
ORDER BY sum(totalDue) DESC LIMIT 1
通过按 sum(totaldue)
排序记录然后仅保留第一条记录 LIMIT 1
来获得最大客户的 sum(totalDue)
。我们在 HAVING
子句中使用它来将其与每个客户的 Sum(totaldue)
进行比较。如果主查询中的客户有一个 sum(totaldue)
相当于子查询的结果,那么我们保留记录。
postgres=> CREATE TABLE salesorderheader
postgres-> (
postgres(> customerid integer,
postgres(> totaldue integer
postgres(> );
CREATE TABLE
postgres=> INSERT INTO salesorderheader VALUES
postgres-> (1, 10),
postgres-> (1, 12),
postgres-> (2, 22),
postgres-> (3, 5),
postgres-> (4, 4);
INSERT 0 5
postgres=> SELECT customerid, sum(totaldue) FROM SalesOrderHeader GROUP BY customerid HAVING sum(totaldue) = (SELECT sum(totaldue) FROM SalesOrderHeader GROUP BY customerID ORDER BY sum(totalDue) desc LIMIT 1);
customerid | sum
------------+-----
1 | 22
2 | 22
(2 rows)
我建议在子查询中对 totaldue
的总和使用 window function rank()
:
SELECT customerid, total_money_paid
FROM (
SELECT customerid, sum(totaldue) AS total_money_paid
, rank() OVER (ORDER BY sum(totaldue) DESC NULLS LAST) AS rnk
FROM salesorderheader
GROUP BY 1
) sub
WHERE rnk = 1;
这样,table 只被扫描 一次 。应该更快。
Window 函数在 在 普通聚合函数之后计算,因此这是可能的。相关:
- Postgres window function and group by exception
NULLS LAST
只有当总和可以是 NULL
时才需要(即 totaldue
可以是 NULL
)。详情:
- PostgreSQL sort by datetime asc, null first?
我选择这个技术是因为你的要求:
show the 1 (or more, in case of a tie) customer
如果你想要正好 1(以某种方式打破关系,如果有更多),那么DISTINCT ON
会更可取:
- Select first row in each GROUP BY group?
我有一个自行车商店的数据库,table 我打电话给
"SalesOrderHeader"
其中包括以下 2 列:CustomerID
、TotalDue
。
它包含有关自行车商店所有销售的信息。所以如果f.e。一个顾客在商店里总共买了 2 次,他的 CustomerID
会有 2 个记录,每次他支付的金额 (TotalDue
)。
如何编写一个 select 查询来显示支付总额最高的 1 个(或多个,如果是平局)客户。结果必须显示 2 列,一列带有 CustomerID
,一列带有 TotalMoneyHePaid
。
您可以在 HAVING 子句中使用子查询来获取:
SELECT customerid,
sum(totaldue)
FROM SalesOrderHeader
GROUP BY customerid
HAVING sum(totaldue) = (
SELECT sum(totaldue)
FROM SalesOrderHeader
GROUP BY customerID
ORDER BY sum(totalDue) DESC LIMIT 1
)
子查询:
SELECT sum(totaldue)
FROM SalesOrderHeader
GROUP BY customerID
ORDER BY sum(totalDue) DESC LIMIT 1
通过按 sum(totaldue)
排序记录然后仅保留第一条记录 LIMIT 1
来获得最大客户的 sum(totalDue)
。我们在 HAVING
子句中使用它来将其与每个客户的 Sum(totaldue)
进行比较。如果主查询中的客户有一个 sum(totaldue)
相当于子查询的结果,那么我们保留记录。
postgres=> CREATE TABLE salesorderheader
postgres-> (
postgres(> customerid integer,
postgres(> totaldue integer
postgres(> );
CREATE TABLE
postgres=> INSERT INTO salesorderheader VALUES
postgres-> (1, 10),
postgres-> (1, 12),
postgres-> (2, 22),
postgres-> (3, 5),
postgres-> (4, 4);
INSERT 0 5
postgres=> SELECT customerid, sum(totaldue) FROM SalesOrderHeader GROUP BY customerid HAVING sum(totaldue) = (SELECT sum(totaldue) FROM SalesOrderHeader GROUP BY customerID ORDER BY sum(totalDue) desc LIMIT 1);
customerid | sum
------------+-----
1 | 22
2 | 22
(2 rows)
我建议在子查询中对 totaldue
的总和使用 window function rank()
:
SELECT customerid, total_money_paid
FROM (
SELECT customerid, sum(totaldue) AS total_money_paid
, rank() OVER (ORDER BY sum(totaldue) DESC NULLS LAST) AS rnk
FROM salesorderheader
GROUP BY 1
) sub
WHERE rnk = 1;
这样,table 只被扫描 一次 。应该更快。 Window 函数在 在 普通聚合函数之后计算,因此这是可能的。相关:
- Postgres window function and group by exception
NULLS LAST
只有当总和可以是 NULL
时才需要(即 totaldue
可以是 NULL
)。详情:
- PostgreSQL sort by datetime asc, null first?
我选择这个技术是因为你的要求:
show the 1 (or more, in case of a tie) customer
如果你想要正好 1(以某种方式打破关系,如果有更多),那么DISTINCT ON
会更可取:
- Select first row in each GROUP BY group?