2012-12-12 41 views
4

我基本上有一個表,其中包含每個日期的計數。我想創建一個查詢,該查詢給出了整個表上的計數總數,以及昨天的總數。但是當我嘗試加入表格兩次時,聚合關閉。以下是您可以如何複製結果。mysql當我連接兩次表相同的表聚合是錯誤的

CREATE TABLE a (id int primary key); 
CREATE TABLE b (a_id int, b_id int, date date, count int, primary key (a_id,b_id,date)); 
INSERT INTO a VALUES (1); 
INSERT INTO b VALUES (1, 1, UTC_DATE(), 5); 
INSERT INTO b VALUES (1, 2, UTC_DATE(), 10); 
INSERT INTO b VALUES (1, 1, UTC_DATE()-1, 7); 
INSERT INTO b VALUES (1, 2, UTC_DATE()-1, 12); 

SELECT A.id,SUM(B.count) AS total_count,SUM(Y.count) AS y FROM a AS A 
LEFT JOIN b AS B ON (B.a_id=A.id) 
LEFT JOIN b AS Y ON (Y.a_id=A.id AND Y.date=UTC_DATE()-1) 
GROUP BY A.id; 

Results in: 
+----+-------------+------+ 
| id | total_count | y | 
+----+-------------+------+ 
| 1 |   68 | 76 | 
+----+-------------+------+ 


The correct result should be: 
+----+-------------+------+ 
| id | total_count | y | 
+----+-------------+------+ 
| 1 |   34 | 22 | 
+----+-------------+------+ 

這是怎麼回事?這是一個在MySQL中的錯誤,或者我不理解連接如何工作。

回答

7

不,它不是MySQL中的錯誤。

您的JOIN條件正在生成「重複」行。 (刪除聚合函數和GROUP BY,你會看到發生了什麼

表「a」中的那行與表「b」中的四行相匹配,這很好,但是當你添加加入第三個表格(「y」),從第三個「y」表格(兩行)返回的每一行都與「b」表格中的每一行「匹配」......因此, (這就是爲什麼「total_count」會增加一倍)

要獲得您指定的結果集,您不需要第二次連接該表「b」,而只需使用一個有條件的測試,以確定這個「計數」是否應該包含在「y」總數中。

例如

SELECT a.id 
    , SUM(b.count) AS total_count 
    , SUM(IF(b.date=UTC_DATE()-1 ,b.count,0)) AS y 
    FROM a a 
    LEFT 
    JOIN b b ON (b.a_id=a.id) 
GROUP BY a.id; 

注意的是,MySQL的IF表達可以用等效ANSI CASE表達,以提高便攜性所取代:

 , SUM(CASE WHEN b.date=UTC_DATE()-1 THEN b.count ELSE 0 END) AS y 

如果你是想做加盟到「B 「表格第二次,你會想JOIN條件是這樣的,從」Y「行最多匹配一行」B「,以免引入任何重複。所以你基本上需要連接條件來包含主鍵中的所有列。

(請注意,在表中的「y」保證連接條件的謂詞,每個從「Y」將會從「B」匹配不超過一個行):

SELECT a.id 
    , SUM(b.count) AS total_count 
    , SUM(y.count) AS y 
    FROM a a 
    LEFT 
    JOIN b b 
    ON b.a_id=a.id 
    LEFT 
    JOIN b y 
    ON y.a_id = b.a_id 
    AND y.b_id = b.b_id 
    AND y.date = b.date 
    AND y.date = UTC_DATE()-1 
GROUP BY a.id; 

(要獲得到位零的返回結果集相同,與潛在的NULL先聲明,你就需要更換「0」與「空」的IF表達不變。

 , SUM(IF(b.date=UTC_DATE()-1 ,b.count,NULL)) AS y 
+0

謝謝,首先我介紹了mysql IF語句。這是最後工作的查詢:SELECT a.id,SUM(b.count)AS total_count,SUM(IF(b.date = UTC_DATE() - 1,b.count,0))FROM aa LEFT JOIN bb ON (b.a_id = a.id)GROUP BY a.id; –

4
SELECT A.id,b_count AS total_count,y_count as y 
FROM a AS A 
LEFT JOIN (select a_id,SUM(B.Count) b_count from b 
       group by B.A_id) AS B1 ON (B1.a_id=A.id) 
LEFT JOIN (select a_id,SUM(Count) y_count from b 
       where date=UTC_DATE()-1 
      group by B.A_id) AS Y ON (Y.a_id=A.id) 

SQLFiddle Demo

+1

+1。這將返回指定的結果集。使用這種方法時需要考慮性能方面的問題,特別是內聯視圖(或者用MySQL的說法,派生表)。 MySQL將把這些實現爲(中間)MyISAM表,我不相信MySQL會爲這些表創建任何索引。對於小型組來說不是問題,但可能是大型表的性能問題。 – spencer7593