2014-09-29 54 views
1

我有以下三個表格表示樹結構。 #A中的每一行都是#B中零行或更多行的祖先。同樣,#B中的每一行都是#C中零行或更多行的祖先。表#B包含一列value。我需要爲屬於輸入祖先的#B中的所有行找到value的總和。總結查詢結果的不同元素

例如,考慮表的內容如下:

CREATE TABLE #A (id varchar(10)); 
CREATE TABLE #B (id varchar(10), value int); 
CREATE TABLE #C (id varchar(10), a_id varchar(10), b_id varchar(10)); 

INSERT INTO #A(id) VALUES ('A1'), ('A2'); 
INSERT INTO #B(id, value) VALUES('B1', 41), ('B2', 43), ('B3', 47); 
INSERT INTO #C(id, a_id, b_id) VALUES('C1', 'A1', 'B1'), ('C2', 'A1', 'B1'), 
            ('C3', 'A1', 'B2'), ('C4', 'A2', 'B3'); 

以上內容表示如下結構:

A1 
|--- B1 (41) 
| |-------- C1 
| |-------- C2 
| 
|--- B2 (43) 
    |-------- C3 
A2 
|--- B3 (47) 
    |-------- C4 

的父 - 子關係被古怪定義。表#B沒有自己的列表,表#A中的哪一行是它的祖先。所有映射都應根據表#C進行評估。列表a_idb_id分別在表#C中指定祖父母行和父行分別在表#A#B中。如果有一排Z#C其中a_idXb_idY,然後XYY祖先是Z祖先。在#C中不會有衝突的映射。

問題陳述:對於給定的ID A1,發現value列的所有行中#B,其父母爲A1的總和。這裏有兩個孩子A1,B1其值爲41B2的值爲43所以我們期望答案是84

如果我這樣做如下:

SELECT SUM(#B.value) FROM #B 
INNER JOIN #C ON #B.id = #C.b_id 
INNER JOIN #A ON #C.a_id = #A.id 
WHERE #A.id = 'A1' 

我得到12541 + 41 + 43代替84,因爲在#A兩行具有映射B1 -> C1。我可以寫下面的查詢來獲取與#B中的不同行相關聯的值,即4143,但是現在我不知道如何對結果值進行求和。我能否在不創建臨時表的情況下獲得預期結果?

SELECT MAX(#B.value) FROM #B 
INNER JOIN #C ON #B.id = #C.b_id 
INNER JOIN #A ON #C.a_id = #A.id 
WHERE #A.id = 'A1' 
GROUP BY #B.id; 

我不是SQL專家,所以可能會有一個非常簡單的解決方案。

回答

1

你不這裏需要表#A,因爲這些ID在表#C中,表中的值在表#B中。這就是你所需要的。無需加入。只需從#C中選擇所需的ID,然後使用它們從#B中選擇。

select sum(value) 
from #B 
where id in 
(
    select b_id 
    from #C 
    where a_id = 'A1' 
); 
+0

這是最簡單的解決方案。正如你所說的,表格#A不是必需的。還有一點要記住:當我們需要刪除重複項時,INNER JOIN'不能替代WHERE-IN子句。 – 2014-09-29 13:55:51

1

你可以這樣做:

SELECT SUM(#B.value) 
FROM #B 
WHERE EXISTS 
(
    SELECT NULL FROM #C 
    INNER JOIN #A ON #C.a_id = #A.id 
    WHERE #B.id = #C.b_id 
    AND #A.id = 'A1' 
) 

然後在那裏的其他表中存在,你將只能總結#B

結果將是:84

0

稍有不同的方法。

SELECT SUM(#B.value) FROM #B 
INNER JOIN (
    SELECT DISTINCT a_id, b_id FROM #C 
) temp 
ON 
temp.b_id=#B.ID 
WHERE temp.a_id='A1'; 

這樣做的好處是可以改變WHERE temp.a_id='A1'GROUP BY temp.a