簡體   English   中英

具有SUM,GROUP BY和JOIN的SQL聚合(多對多)

[英]SQL Aggregation with SUM, GROUP BY and JOIN (many-to-many)

這是表格布局的示例:

TABLE_A:                    TABLE_B:     TABLE_A_B:
id | a     | b    | c       id | name    a_id | b_id
---------------------       ---------    -----------
1  | true  | X    | A       1  | A       1    | 1
2  | true  | Z    | null    2  | B       1    | 2
3  | false | X    | null    3  | C       2    | 2
4  | true  | Y    | Q                    4    | 1
5  | false | null | null                 4    | 2
                                         5    | 1

可能的值:

  • TABLE_A.a:是,否
  • TABLE_A.b:X,Y,Z
  • TABLE_A.c:A,B,C ...基本上是任意的
  • TABLE_B.name:A、B、C ...基本上是任意的

我要實現的目標:

SELECT all rows from TABLE_A
  SUM(where a = true),
  SUM(where a = false),
  SUM(where b = 'X'),
  SUM(where b = 'Y'),
  SUM(where b = 'Z'),
  SUM(where b IS NULL),
and also get the SUMs for all distinct TABLE_A.c values.
and also get the SUMs for all those TABLE_A_B relations.

上面的示例表的結果應如下所示:

aTrue | aFalse | bX | bY | bZ | bNull | cA | cQ | cNull | nameA | nameB | nameC
-------------------------------------------------------------------------------
3     | 2      | 2  | 1  | 1  | 1     | 1  | 1  | 3     | 3     | 3     | 0

到目前為止,我所做的是:

SELECT
  SUM(CASE WHEN a = true THEN 1 ELSE 0 END) AS aTrue,
  SUM(CASE WHEN b = false THEN 1 ELSE 0 END) AS aFalse,
  SUM(CASE WHEN b = 'X' THEN 1 ELSE 0 END) AS bX,
  ...
FROM TABLE_A

我怎么了

選擇TABLE_A.aTABLE_A.b列很容易,因為存在固定數量的可能值。

但是我不知道如何計算TABLE_A.c的不同值。 基本上同樣的問題對於加盟TABLE_B因為中值的數量TABLE_B是未知的,可以隨時間而改變。

謝謝你的幫助! :)

EDIT1:新的(首選)SQL結果結構:

column         | value | sum
----------------------------
TABLE_A.a      | true  | 3
TABLE_A.a      | false | 2
TABLE_A.b      | X     | 2
TABLE_A.b      | Y     | 1
TABLE_A.b      | Z     | 1
TABLE_A.b      | null  | 1
TABLE_A.c      | A     | 1
TABLE_A.c      | Q     | 1
TABLE_A.c      | null  | 3
TABLE_B.name   | A     | 3
TABLE_B.name   | B     | 3
TABLE_B.name   | C     | 0

從您最初對行的請求作為模擬樞軸。 通過執行SUM(邏輯條件),如果為true,則基本上返回1,如果為false,則返回0。 因此,由於列“ a”是對還是錯,所以“ a”或NOT“ a”的簡單總和(對於錯誤計數-NOT FALSE = TRUE)。 同樣,您的“ b”列,因此b ='X'= true計為1,否則計為0。

在其他SQL引擎中,您可能將其視為SUM(case / when)。

現在,由於您的表計數不再相互依賴,因此可以將SUM()分為各自的子別名查詢引用(分別對於pre-queryA和pre-queryB使用pqA和pqB)。 由於沒有分組依據,因此它們各自將導致一行。 沒有連接將創建笛卡爾,但由於比例為1:1,因此僅返回所需所有列的單個記錄。

SELECT 
      pqA.*, pqB.*
   from
      ( SELECT
              SUM( ta.a ) aTrue,
              SUM( NOT ta.a ) aFalse,
              SUM( ta.b = 'X' ) bX,
              SUM( ta.b = 'Y' ) bY,
              SUM( ta.b = 'Z' ) bZ,
              SUM( ta.b is null ) bNULL,
              SUM( ta.c = 'A' ) cA,
              SUM( ta.c = 'Q' ) cQ,
              SUM( ta.c is null ) cNULL,
              COUNT( distinct ta.c ) DistC
           from
              table_a ta ) pqA,
      ( SELECT
              SUM( b.Name = 'A' ) nameA,
              SUM( b.Name = 'B' ) nameB,
              SUM( b.Name = 'C' ) nameC
           from
              table_a_b t_ab 
                 join table_b b
                    ON t_ab.b_id = b.id ) pqB

此選項提供您的第二個(首選)輸出

SELECT
      MAX( 'TABLE_A.a   ' ) as Basis,
      CASE when a then 'true' else 'false' end Value,
      COUNT(*) finalCnt
   from
      TABLE_A
   group by
      a
UNION ALL
SELECT
      MAX( 'TABLE_A.b   ' ) as Basis,
      b Value,
      COUNT(*) finalCnt
   from
      TABLE_A
   group by
      b
UNION ALL
SELECT
      MAX( 'TABLE_A.c   ' ) as Basis,
      c Value,
      COUNT(*) finalCnt
   from
      TABLE_A
   group by
      c
UNION ALL
SELECT
      MAX( 'TABLE_B.name   ' ) as Basis,
      b.Name Value,
      COUNT(*) finalCnt
   from
      table_a_b t_ab 
         join table_b b
            ON t_ab.b_id = b.id 
   group by
      b.Name

我認為您將需要構建動態查詢,因為您不知道表A中C列的可能值。因此,您可以編寫存儲過程,在其中可以在一個變量中使用“ Do WHILE”獲取C列的不同值的列表。您可以構建動態查詢。 如果您需要更多詳細的動態SQL請讓我知道

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM