2012-10-16 68 views
5

我有以下結構:SQL:僅用於不同ID的值的總和 - 條件和?

包含typ1和typ2多個事件的日子,其中typ1和typ2具有外鍵到它們各自的日子。 Typ2也有持續時間。

現在我要計算所有typ1事件,所有typ2事件和typ2持續時間的總和。

實施例的數據:

天:

ID = 1 | Date = yesterday | ... 

TYP1:

ID = 1 | FK_DAY = 1 | ... 

ID = 2 | FK_DAY = 1 | ... 

TYP2:

ID = 1 | FK_DAY = 1 | duration = 10 

ID = 2 | FK_DAY = 1 | duration = 20 

我現在想要的結果:

Day.ID = 1 | countTyp1 = 2 | countTyp2 = 2 | sumDurationTyp2 = 30 

我的問題是總和,我需要像「總和爲不同typ2.ID」...有沒有人知道一種方法來解決這個問題?

我使用類似於以下,但這當然不工作的方式我想:

SELECT day.id, 
    count(DISTINCT typ1.id), 
    count(DISTINCT typ2.id), 
    sum(duration) AS duration 
FROM days 
    LEFT JOIN typ 
      ON day.id = typ1.id 
    LEFT JOIN typ2 
      ON day.id = typ2.id 
GROUP BY day.id; 
+0

什麼RDBMS和什麼版本? – Tobsey

回答

13

我這種一般的方法是預先彙總每個表中,在加入之前。部分原因是你實際上並沒有求和不同的值(如果兩行中的每一行都有10,答案仍然是20)。

但主要是因爲它實際上更簡單。子查詢進行聚合,然後連接都是1:1。

SELECT 
    days.id, 
    typ_agg.rows, 
    type2_agg.rows, 
    type2_agg.duration 
FROM 
    days 
LEFT JOIN 
    (SELECT fk_day, COUNT(*) as rows FROM typ GROUP BY fk_day) AS typ_agg 
    ON days.id = typ_agg.fk_day 
LEFT JOIN 
    (SELECT fk_day, COUNT(*) as rows, SUM(duration) as duration FROM typ2 GROUP BY fk_day) AS typ2_agg 
    ON days.id = typ2_agg.fk_day 
+1

。 。我希望這是被接受的答案,因爲這是正確的方法。 –

+0

非常感謝,在我的實際查詢中更復雜,這使得它更具可讀性 – prom85

0
SELECT day.id, 
    count(DISTINCT typ1.id), 
    count(DISTINCT typ2.id), 
    (select sum(t2.duration) 
    from typ2 t2 
    where t2.id = day.id 
    ) AS duration 
FROM days 
    LEFT JOIN typ 
      ON day.id = typ1.id 
    LEFT JOIN typ2 
      ON day.id = typ2.id 
GROUP BY day.id; 
+0

這引入了額外的子查詢,我相信OP正在尋找一個單一的查詢解決方案。你的答案是否意味着暗示它不能被寫成單個查詢? – Yuck

+0

@Yuck - 它說「單個查詢」或「無子查詢」。爲什麼你認爲「子查詢」不是「單個查詢」的一部分? *(如果它們是某個「子」的東西,它們就是它的一部分,而它是一個單一的查詢......)更不用說某些RDBMS在擴展子查詢時是例外的。 – MatBailie

+0

FWIW,這不是我downvote。至少在SQL Server中,這種類型的查詢通常具有嚴格的性能損失。並不是它錯了。我只是在問這個問題 - 是否有辦法做到這一點,而不是選擇涉及的表格? – Yuck