使用多列时无法将 PARTITION BY 与 COUNT(*) 一起使用
Unable to use PARTITION BY with COUNT(*) when multiple columns are used
假设我有一个包含以下列的 table:
- 类型
- 部门
- 供应商
- 订购
- 总计
我想查询此数据,以便获得有序结果,首先按类型分组。订单是订单数量。然后下面的查询对我来说很好 (http://sqlfiddle.com/#!15/78cc1/1):
WITH company_sales(type, department, supplier, order_number, total) AS (
VALUES
('Edibles' , 'Department-1', 'Supplier-1' , 'ORDER-1' , 10)
, ('Edibles' , 'Department-1', 'Supplier-2' , 'ORDER-2' , 20)
, ('Edibles' , 'Department-1', 'Supplier-3' , 'ORDER-3' , 30)
, ('Edibles' , 'Department-1', 'Supplier-4' , 'ORDER-4' , 40)
, ('Edibles' , 'Department-2', 'Supplier-5' , 'ORDER-5' , 50)
, ('Edibles' , 'Department-2', 'Supplier-6' , 'ORDER-6' , 60)
, ('Edibles' , 'Department-3', 'Supplier-7' , 'ORDER-7' , 70)
, ('Edibles' , 'Department-3', 'Supplier-8' , 'ORDER-8' , 80)
, ('Edibles' , 'Department-3', 'Supplier-9' , 'ORDER-9' , 90)
, ('Edibles' , 'Department-3', 'Supplier-9' , 'ORDER-10', 100)
, ('Edibles' , 'Department-4', 'Supplier-10', 'ORDER-11', 110)
, ('Non-Edibles', 'Department-2', 'Supplier-11', 'ORDER-12', 1000)
, ('Non-Edibles', 'Department-3', 'Supplier-12', 'ORDER-13', 1010)
, ('Non-Edibles', 'Department-3', 'Supplier-13', 'ORDER-14', 1020)
, ('Non-Edibles', 'Department-3', 'Supplier-14', 'ORDER-15', 1030)
, ('Non-Edibles', 'Department-3', 'Supplier-14', 'ORDER-16', 1040)
, ('Non-Edibles', 'Department-4', 'Supplier-15', 'ORDER-17', 1050)
)
SELECT cs.type,
count(*) sum_total_count,
sum(total) sum_grand_total
FROM company_sales cs
GROUP BY cs.type
ORDER BY Sum(Count(*)) OVER (partition BY cs.type) DESC,
cs.type ASC;
如果我想查询此数据以获得有序结果,首先按类型分组,然后按部门分组。订单是订单数量。然后下面的查询对我来说很好 (http://sqlfiddle.com/#!15/78cc1/2):
WITH company_sales(type, department, supplier, order_number, total) AS ( ...)
SELECT cs.type,
cs.department,
count(*) sum_total_count,
sum(total) sum_grand_total
FROM company_sales cs
GROUP BY cs.type,
cs.department
ORDER BY Sum(Count(*)) OVER (partition BY cs.type) DESC,
Sum(Count(*)) OVER (partition BY cs.type, cs.department) DESC,
cs.type ASC,
cs.department ASC;
但是,当我想要有序的结果时遵循相同的模式,首先按类型分组,然后按部门分组,然后按供应商分组,顺序是订单数。然后下面的查询对我不起作用 (http://sqlfiddle.com/#!15/78cc1/3):
WITH company_sales(type, department, supplier, order_number, total) AS (...)
SELECT cs.type,
cs.department,
cs.supplier,
count(*) sum_total_count,
sum(total) sum_grand_total
FROM company_sales cs
GROUP BY cs.type,
cs.department,
cs.supplier
ORDER BY Sum(Count(*)) OVER (partition BY cs.type) DESC,
Sum(Count(*)) OVER (partition BY cs.type, cs.department) DESC,
Sum(Count(*)) OVER (partition BY cs.type, cs.department, cs.supplier) DESC,
cs.type ASC,
cs.department ASC,
cs.supplier ASC;
以上查询结果如下:
然而,我想要以下内容:
我哪里错了?
两场预赛:
- 永远不会 使用 SQL 列名称的保留关键字。接下来是
type -> typ
和 order -> ordnum
.
- 学习使用
VALUES
子句。我建议您根据以下示例编辑您的问题,无需重复 3 次(只需使用 WITH company_sales (...) AS (...) SELECT ...
之类的内容;例如,PG 手册就是这样做的)。实际上,您的问题太冗长了,人们不会通读。 (好的 - Erwin Brandstetter 从 OP 中编辑了这个)
第一
查询 returns 结果的顺序不符合您的要求,因为您以错误的顺序指定了 ORDER BY
子句。在 typ = 'Edibles'
下,部门 1 和部门 3 都有 4 个订单。分析您的 ORDER BY
子句,我们看到以下内容:
-- 1. This orders by the type with the most orders - OK
ORDER BY Sum(Count(*)) OVER (PARTITION BY cs.type) DESC,
-- 2. Number of orders by department within each type - OK but tie #1 and #3
Sum(Count(*)) OVER (PARTITION BY cs.type, cs.department) DESC,
-- 3. Number of orders by supplier with each type, department - NOT OK
Sum(Count(*)) OVER (PARTITION BY cs.type, cs.department, cs.supplier) DESC,
-- 4. In case of ties, order by type name - OK
cs.type ASC,
-- 5. In case of ties, order by department name - OK
cs.department ASC,
-- 6. In case of ties, order by supplier name - OK
cs.supplier ASC;
那么为什么#3 不正常?事实上,#3 很好,但#4、#5 和#6 放错了地方。您希望按类型数、部门数、供应商数排序,并按字母顺序解决关系。您应该在每次对行数进行排序后立即解决这些关系(删除过时的 table 别名和 ASC
子句):
ORDER BY
Sum(Count(*)) OVER (PARTITION BY typ) DESC, typ,
Sum(Count(*)) OVER (PARTITION BY typ, department) DESC, department,
Sum(Count(*)) OVER (PARTITION BY typ, department, supplier) DESC, supplier;
那为什么你点错了?好吧,'Edibles' 中的部门 1 和部门 3 各有 4 行,因此它们是并列的。以下子句对供应商 9 的 2 个订单的排序高于其他供应商,每个供应商的 1 个订单。在供应商订单之前按部门名称排序会打破部门之间的联系,并且所有行的顺序都很好。
然后
子句Sum(Count(*)) OVER (PARTITION BY ...)
是无稽之谈。 count(*)
为分区中的每一行分配一个新列,其中包含该分区中的行数。再次求和得到与基本行数完全相同的排序属性的正方形。
此外,Sum(Count(*)) OVER (PARTITION BY typ, department, supplier)
是无用的,因为您已经 GROUP BY
这些相同的列在 select 列表中生成 count(*)
。
给予
将所有这些放在一起并为简洁起见使用位置参数,我们得到:
WITH company_sales(typ, department, supplier, ordnum, total) AS (...)
SELECT typ,
department,
supplier,
count(*) sum_total_count,
sum(total) sum_grand_total
FROM company_sales
GROUP BY 1, 2, 3
ORDER BY
count(*) OVER (PARTITION BY typ) DESC, 1,
count(*) OVER (PARTITION BY typ, department) DESC, 2,
4 DESC, 3;
导致:
typ | department | supplier | sum_total_count | sum_grand_total
-------------+--------------+-------------+-----------------+-----------------
Edibles | Department-1 | Supplier-1 | 1 | 10
Edibles | Department-1 | Supplier-2 | 1 | 20
Edibles | Department-1 | Supplier-3 | 1 | 30
Edibles | Department-1 | Supplier-4 | 1 | 40
Edibles | Department-3 | Supplier-9 | 2 | 190
Edibles | Department-3 | Supplier-7 | 1 | 70
Edibles | Department-3 | Supplier-8 | 1 | 80
Edibles | Department-2 | Supplier-5 | 1 | 50
Edibles | Department-2 | Supplier-6 | 1 | 60
Edibles | Department-4 | Supplier-10 | 1 | 110
Non-Edibles | Department-3 | Supplier-12 | 1 | 1010
Non-Edibles | Department-3 | Supplier-13 | 1 | 1020
Non-Edibles | Department-3 | Supplier-14 | 2 | 2070
Non-Edibles | Department-2 | Supplier-11 | 1 | 1000
Non-Edibles | Department-4 | Supplier-15 | 1 | 1050
(15 rows)
假设我有一个包含以下列的 table:
- 类型
- 部门
- 供应商
- 订购
- 总计
我想查询此数据,以便获得有序结果,首先按类型分组。订单是订单数量。然后下面的查询对我来说很好 (http://sqlfiddle.com/#!15/78cc1/1):
WITH company_sales(type, department, supplier, order_number, total) AS (
VALUES
('Edibles' , 'Department-1', 'Supplier-1' , 'ORDER-1' , 10)
, ('Edibles' , 'Department-1', 'Supplier-2' , 'ORDER-2' , 20)
, ('Edibles' , 'Department-1', 'Supplier-3' , 'ORDER-3' , 30)
, ('Edibles' , 'Department-1', 'Supplier-4' , 'ORDER-4' , 40)
, ('Edibles' , 'Department-2', 'Supplier-5' , 'ORDER-5' , 50)
, ('Edibles' , 'Department-2', 'Supplier-6' , 'ORDER-6' , 60)
, ('Edibles' , 'Department-3', 'Supplier-7' , 'ORDER-7' , 70)
, ('Edibles' , 'Department-3', 'Supplier-8' , 'ORDER-8' , 80)
, ('Edibles' , 'Department-3', 'Supplier-9' , 'ORDER-9' , 90)
, ('Edibles' , 'Department-3', 'Supplier-9' , 'ORDER-10', 100)
, ('Edibles' , 'Department-4', 'Supplier-10', 'ORDER-11', 110)
, ('Non-Edibles', 'Department-2', 'Supplier-11', 'ORDER-12', 1000)
, ('Non-Edibles', 'Department-3', 'Supplier-12', 'ORDER-13', 1010)
, ('Non-Edibles', 'Department-3', 'Supplier-13', 'ORDER-14', 1020)
, ('Non-Edibles', 'Department-3', 'Supplier-14', 'ORDER-15', 1030)
, ('Non-Edibles', 'Department-3', 'Supplier-14', 'ORDER-16', 1040)
, ('Non-Edibles', 'Department-4', 'Supplier-15', 'ORDER-17', 1050)
)
SELECT cs.type,
count(*) sum_total_count,
sum(total) sum_grand_total
FROM company_sales cs
GROUP BY cs.type
ORDER BY Sum(Count(*)) OVER (partition BY cs.type) DESC,
cs.type ASC;
如果我想查询此数据以获得有序结果,首先按类型分组,然后按部门分组。订单是订单数量。然后下面的查询对我来说很好 (http://sqlfiddle.com/#!15/78cc1/2):
WITH company_sales(type, department, supplier, order_number, total) AS ( ...)
SELECT cs.type,
cs.department,
count(*) sum_total_count,
sum(total) sum_grand_total
FROM company_sales cs
GROUP BY cs.type,
cs.department
ORDER BY Sum(Count(*)) OVER (partition BY cs.type) DESC,
Sum(Count(*)) OVER (partition BY cs.type, cs.department) DESC,
cs.type ASC,
cs.department ASC;
但是,当我想要有序的结果时遵循相同的模式,首先按类型分组,然后按部门分组,然后按供应商分组,顺序是订单数。然后下面的查询对我不起作用 (http://sqlfiddle.com/#!15/78cc1/3):
WITH company_sales(type, department, supplier, order_number, total) AS (...)
SELECT cs.type,
cs.department,
cs.supplier,
count(*) sum_total_count,
sum(total) sum_grand_total
FROM company_sales cs
GROUP BY cs.type,
cs.department,
cs.supplier
ORDER BY Sum(Count(*)) OVER (partition BY cs.type) DESC,
Sum(Count(*)) OVER (partition BY cs.type, cs.department) DESC,
Sum(Count(*)) OVER (partition BY cs.type, cs.department, cs.supplier) DESC,
cs.type ASC,
cs.department ASC,
cs.supplier ASC;
以上查询结果如下:
然而,我想要以下内容:
我哪里错了?
两场预赛:
- 永远不会 使用 SQL 列名称的保留关键字。接下来是
type -> typ
和order -> ordnum
. - 学习使用
VALUES
子句。我建议您根据以下示例编辑您的问题,无需重复 3 次(只需使用WITH company_sales (...) AS (...) SELECT ...
之类的内容;例如,PG 手册就是这样做的)。实际上,您的问题太冗长了,人们不会通读。 (好的 - Erwin Brandstetter 从 OP 中编辑了这个)
第一
查询 returns 结果的顺序不符合您的要求,因为您以错误的顺序指定了 ORDER BY
子句。在 typ = 'Edibles'
下,部门 1 和部门 3 都有 4 个订单。分析您的 ORDER BY
子句,我们看到以下内容:
-- 1. This orders by the type with the most orders - OK
ORDER BY Sum(Count(*)) OVER (PARTITION BY cs.type) DESC,
-- 2. Number of orders by department within each type - OK but tie #1 and #3
Sum(Count(*)) OVER (PARTITION BY cs.type, cs.department) DESC,
-- 3. Number of orders by supplier with each type, department - NOT OK
Sum(Count(*)) OVER (PARTITION BY cs.type, cs.department, cs.supplier) DESC,
-- 4. In case of ties, order by type name - OK
cs.type ASC,
-- 5. In case of ties, order by department name - OK
cs.department ASC,
-- 6. In case of ties, order by supplier name - OK
cs.supplier ASC;
那么为什么#3 不正常?事实上,#3 很好,但#4、#5 和#6 放错了地方。您希望按类型数、部门数、供应商数排序,并按字母顺序解决关系。您应该在每次对行数进行排序后立即解决这些关系(删除过时的 table 别名和 ASC
子句):
ORDER BY
Sum(Count(*)) OVER (PARTITION BY typ) DESC, typ,
Sum(Count(*)) OVER (PARTITION BY typ, department) DESC, department,
Sum(Count(*)) OVER (PARTITION BY typ, department, supplier) DESC, supplier;
那为什么你点错了?好吧,'Edibles' 中的部门 1 和部门 3 各有 4 行,因此它们是并列的。以下子句对供应商 9 的 2 个订单的排序高于其他供应商,每个供应商的 1 个订单。在供应商订单之前按部门名称排序会打破部门之间的联系,并且所有行的顺序都很好。
然后
子句Sum(Count(*)) OVER (PARTITION BY ...)
是无稽之谈。 count(*)
为分区中的每一行分配一个新列,其中包含该分区中的行数。再次求和得到与基本行数完全相同的排序属性的正方形。
此外,Sum(Count(*)) OVER (PARTITION BY typ, department, supplier)
是无用的,因为您已经 GROUP BY
这些相同的列在 select 列表中生成 count(*)
。
给予
将所有这些放在一起并为简洁起见使用位置参数,我们得到:
WITH company_sales(typ, department, supplier, ordnum, total) AS (...)
SELECT typ,
department,
supplier,
count(*) sum_total_count,
sum(total) sum_grand_total
FROM company_sales
GROUP BY 1, 2, 3
ORDER BY
count(*) OVER (PARTITION BY typ) DESC, 1,
count(*) OVER (PARTITION BY typ, department) DESC, 2,
4 DESC, 3;
导致:
typ | department | supplier | sum_total_count | sum_grand_total
-------------+--------------+-------------+-----------------+-----------------
Edibles | Department-1 | Supplier-1 | 1 | 10
Edibles | Department-1 | Supplier-2 | 1 | 20
Edibles | Department-1 | Supplier-3 | 1 | 30
Edibles | Department-1 | Supplier-4 | 1 | 40
Edibles | Department-3 | Supplier-9 | 2 | 190
Edibles | Department-3 | Supplier-7 | 1 | 70
Edibles | Department-3 | Supplier-8 | 1 | 80
Edibles | Department-2 | Supplier-5 | 1 | 50
Edibles | Department-2 | Supplier-6 | 1 | 60
Edibles | Department-4 | Supplier-10 | 1 | 110
Non-Edibles | Department-3 | Supplier-12 | 1 | 1010
Non-Edibles | Department-3 | Supplier-13 | 1 | 1020
Non-Edibles | Department-3 | Supplier-14 | 2 | 2070
Non-Edibles | Department-2 | Supplier-11 | 1 | 1000
Non-Edibles | Department-4 | Supplier-15 | 1 | 1050
(15 rows)