0

次の列を持つテーブルがあるとします。

  • タイプ
  • デパートメント
  • サプライヤー
  • 注文
  • 合計

そして、このデータをクエリして、最初に TYPE でグループ化された順序付けされた結果を取得したいと考えました。注文は注文数です。次に、次のクエリがうまく機能します(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;

このデータにクエリを実行して、最初に TYPE でグループ化し、次に DEPARTMENT でグループ化した順序付けされた結果を取得します。注文は注文数です。次に、次のクエリがうまく機能します(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;

ただし、注文した結果が必要な場合は同じパターンに従います。最初に TYPE でグループ化し、次に DEPARTMENT でグループ化し、次に SUPPLIER でグループ化します。順序は注文数です。次に、次のクエリは機能しません( 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;

上記のクエリの結果は次のようになります。

正しくない結果セット

一方、私は次のことを望んでいます:

望ましい正しい結果セット

どこが間違っていますか?

4

1 に答える 1

2

2 つの予選:

  1. 列名に SQL 予約キーワードを絶対に使用しないでください。以下type -> typおよびorder -> ordnum.
  2. VALUES句の使い方を学びます。以下の例に従って質問を編集することをお勧めします。3 回繰り返す必要はありません (たとえばWITH company_sales (...) AS (...) SELECT ...、PG マニュアルのように使用します)。そのままでは、あなたの質問はあまりにも冗長であり、人々はそれを読み通さないでしょう. (OK - Erwin Brandstetter がこれを OP から切り離して編集しました)

初め

ORDER BY句を間違った順序で指定したため、クエリは必要な順序とは異なる結果を返します。部門 1 と 3のtyp = 'Edibles'両方に 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 は OK ではないのでしょうか。実際、#3 は問題ありませんが、#4、#5、#6 は間違った場所にあります。タイプの番号、部門、サプライヤの順に並べて、アルファベット順に同点を解決します。行数を並べ替えるたびに、これらの関係をすぐに解決する必要があります (廃止されたテーブル エイリアスと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 BYcount(*)

与える

これをすべてまとめて、簡潔にするために位置パラメータを使用すると、次のようになります。

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)
于 2016-01-27T04:27:33.043 に答える