使用多列时无法将 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;

以上查询结果如下:

然而,我想要以下内容:

我哪里错了?

两场预赛:

  1. 永远不会 使用 SQL 列名称的保留关键字。接下来是 type -> typorder -> ordnum.
  2. 学习使用 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)