2013-04-08 61 views
4

我對SQL不太熟悉。我正在使用oracle。我遇到了一個超過總計字段的問題。具有多個連接和組的SQL嵌套總和

下面是例子表:

A: 
    A_ID 
    A_NAME 

B: 
    B_ID 
    A_ID 
    B_NAME 
    B_QTY 
C: 
    C_ID 
    B_ID 
    C_QTY 

因此,數據結構是像A - > * B - > * C

我需要得到B和C的總量由B_NAME分組和A_ID。例如:

A: 
    A_ID A_NAME 
    1  A1 
B: 
    B_ID A_ID B_NAME B_QTY 
    1  1  B1 20 
    2  1  B1 5 
    3  1  B1 5 
    4  1  B2 5 
C: 
    C_ID B_ID C_QTY 
    1  1  3 
    2  1  4 
    4  2  2 
    5  2  1 
    6  3  1 
    7  4  1 

預期的結果是:

A_ID A_NAME B_NAME B_QTY C_QTY 
1  A1  B1  30  11 
1  A1  B2  5  1 

B_QTY在第一行中的30是在20 + 5 + 5

C_QTY的11中的第一結果線是結果3 + 4 + 2 + 1 + 1

這是我的SQL:

select a.A_ID, 
    a.A_NAME, 
    b.B_NAME 
    sum(b.B_QTY), 
    sum(c.C_QTY) 
from A a left outer join B b on b.A_ID = a.A_ID 
left outer join C c on c.B_ID = b.B_ID 
group by a.A_ID 
order by a.A_ID, b.B_NAME 
    where a.XXXX = XXXXX; 

所以問題是:

由於B映射到多個Cs,B_QTY將被疊加多次。我對SQL不是很熟悉,所以我不知道是否有任何簡單的方法來根據某些字段(在我的示例中是B_ID)來區分求和。謝謝!

+0

請提供您試圖在查詢完成什麼更好的解釋。 – OldProgrammer 2013-04-08 02:06:31

+1

示例數據和期望的輸出可能對解釋您的問題有很大的幫助。 – 2013-04-08 02:12:18

+0

更新了示例數據。謝謝:) – Xiezi 2013-04-08 02:33:46

回答

2

這也可以這樣做:

WITH b2 AS 
(SELECT b.*, sum(b.b_qty) over (partition BY b.a_id, b.b_name) b_qty_s 
      FROM b) 
SELECT a.a_id, a.a_name, b2.b_name, b2.b_qty_s, sum(c.c_qty) c_qty_s 
FROM a JOIN b2 ON a.a_id = b2.a_id 
JOIN c ON b2.b_id = c.b_id 
GROUP BY a.a_id,a.a_name, b2.b_name, b2.b_qty_s 

Here is a sqlfiddle demo

1

我創建了一個SQL fiddle for this problem。訣竅是B_QTY不止一次出現在您的結果中。總結一下就是提供了一個人爲的高價值。相反,運行一個子選擇只能使用一次B_NAME!偉大的問題! :^ D

A.B.Cade的答案很酷,但是這個解決方案將適用於很多數據庫。我以前使用SQL Server,Oracle和Informix這種技術。

數據/模式:

create table a (A_ID int, A_NAME char(10)); 
create table b (B_ID int, A_ID int, B_NAME char(10), B_QTY int); 
create table c (C_ID int, B_ID int, C_QTY int); 
-- One dude 
insert into a values (1,'Xiezi'); 
-- 2 orders? of 4 and 3 
insert into b values (1,1,'B1',20); 
insert into b values (2,1,'B1',5); 
insert into b values (3,1,'B1',5); 
insert into b values (4,1,'B2',5); 
-- 2 order with 2 lines each. 
insert into c values (1,1,3); 
insert into c values (2,1,4); 
insert into c values (4,2,2); 
insert into c values (5,2,1); 
insert into c values (6,3,1); 
insert into c values (7,4,1); 

SQL(答案):

select a.A_ID, 
    a.A_NAME, 
    b.B_NAME, 
    (select sum(b2.B_QTY) from b b2 where b2.B_NAME = b.B_NAME) 
    as sum_b_qty, 
    sum(c.C_QTY) 
from a left outer join b on b.A_ID = a.A_ID 
left outer join c on c.B_ID = b.B_ID 
group by a.A_ID, 
    a.A_NAME, 
    b.B_NAME 
order by a.A_ID 
; 

輸出:

A_ID A_NAME B_NAME SUM_B_QTY SUM(C.C_QTY) 
1 Xiezi B1  30  11 
1 Xiezi B2  5   1 
+0

你剛剛編輯你的問題。讓我看看我能否找出並編輯我的答案。 – Jess 2013-04-08 02:38:24

+0

感謝您的快速回復和更新。重點是我需要根據B的字段彙總數量。但多個聯接會導致多次求和。 – Xiezi 2013-04-08 02:43:31

+0

這是否回答你的問題? – Jess 2013-04-08 04:17:52

1

你也可以這樣做:

SELECT DISTINCT A_ID,A_NAME,B_NAME,B_SUM,SUM(C_QTY) OVER(PARTITION BY A_NAME,B_NAME) C_SUM 
FROM (
SELECT A.A_ID,A_NAME,B_NAME,B_ID,SUM(B_QTY) OVER(PARTITION BY A_NAME,B_NAME) B_SUM 
FROM A JOIN B 
ON A.A_ID=B.A_ID) T1 
JOIN C 
ON T1.B_ID=C.B_ID 

enter image description here

+0

這很像@abcade回答 – Bassal 2013-04-08 06:03:54

+0

@Bassal,實際上有一些區別(2窗口功能,而不是一個組,由於連接是不同的,等等),雖然這兩種解決方案共享相同的基本思想在內部查詢中使用「總和分區」並加入此結果而不是原始表 – 2013-04-08 06:11:15

+0

哦..我看到'with',然後停止閱讀剩餘的內容。 @ A.B.Cade更快。這個想法是基本的。 – Gentlezerg 2013-04-08 06:19:07