2012-12-12 218 views
0

我在一個表(A)中有一個東西,它有兩個其他類別(C1,C2) 來自不同表格(MC)的category_id。group by by multiple colums

我想指出在特定類別中呈現多少東西。實況數據的

實施例:

表阿

main_key (unique) stuff_id (non unique) 
    1     7 
    2     6 
    3     3 

表C1

category_id main_key (it is FK for A table) 
    1    1 
    1    2 
    3    1 

表C2

category_id main_key (it is FK for A table) 
    2    3 
    2    1 

表MC

category_id category_name 
    1    blablbl 
    2    asas 
    3    asasa 
... 
之間

關係: C1和A爲多對一 C2和A爲多對一 C1或C2和MC爲多對一

在當前的例子中,我想看到最終結果作爲

stuff_qnt  category_id  category_name 
2     1     blablbl 
2     2     asas 
1     3     asasa 

我如何用一個單一的查詢來實現它?

我的查詢是:

SELECT count(A.stuff_id) as stuff_qnt, MC.category_id, MC.category_name 
FROM A 
LEFT JOIN C1 using(main_key) 
LEFT JOIN C2 using(main_key) 
LEFT JOIN MC ON (C1.category_id = MC.category_id AND C2.category_id = MC.category_id) 
GROUP BY C1.category_id, C2.category_id 

但它讓我錯誤的結果,是我做錯了嗎?

回答

1
SELECT COUNT(*) AS Stuff_Qnt, C.Category_ID, MC.Category_Name 
    FROM MC 
    JOIN (SELECT C1.Category_ID 
      FROM A 
      JOIN C1 ON A.Main_Key = C1.Main_Key 
     UNION ALL 
     SELECT C2.Category_ID 
      FROM A 
      JOIN C2 ON A.Main_Key = C2.Main_Key 
     ) AS C 
    ON C.Category_ID = MC.Category_ID 
GROUP BY C.Category_ID, MC.Category_Name 
ORDER BY C.Category_ID, Stuff_Qnt; 

你需要從C1和C2與加盟一個類別加盟 - 一個類別,你肯定不希望一個笛卡爾乘積,如你與LEFT OUTER JOIN得到,所以你拿將類別ID列表進行聯合,然後彙總並加入MC。

CREATE TABLE A 
(
    main_key INTEGER NOT NULL PRIMARY KEY, 
    stuff_id INTEGER NOT NULL 
); 
INSERT INTO A VALUES(1, 7); 
INSERT INTO A VALUES(2, 6); 
INSERT INTO A VALUES(3, 3); 

CREATE TABLE MC 
(
    category_id INTEGER NOT NULL PRIMARY KEY, 
    category_name VARCHAR(10) NOT NULL 
); 
INSERT INTO mc VALUES(1, "blablbl"); 
INSERT INTO mc VALUES(2, "asas"); 
INSERT INTO mc VALUES(3, "asasa"); 

CREATE TABLE C1 
(
    category_id INTEGER NOT NULL REFERENCES mc, 
    main_key INTEGER NOT NULL REFERENCES a 
); 
INSERT INTO c1 VALUES(1, 1); 
INSERT INTO c1 VALUES(1, 2); 
INSERT INTO c1 VALUES(3, 1); 

CREATE TABLE C2 
(
    category_id INTEGER NOT NULL REFERENCES mc, 
    main_key INTEGER NOT NULL REFERENCES a 
); 
INSERT INTO c2 VALUES(2, 3); 
INSERT INTO c2 VALUES(2, 1); 

SELECT COUNT(*) AS Stuff_Qnt, C.Category_ID, MC.Category_Name 
    FROM MC 
    JOIN (SELECT C1.Category_ID 
      FROM A 
      JOIN C1 ON A.Main_Key = C1.Main_Key 
     UNION ALL 
     SELECT C2.Category_ID 
      FROM A 
      JOIN C2 ON A.Main_Key = C2.Main_Key 
     ) AS C 
    ON C.Category_ID = MC.Category_ID 
GROUP BY C.Category_ID, MC.Category_Name 
ORDER BY C.Category_ID, Stuff_Qnt; 

輸出:

2 1 blablbl 
2 2 asas 
1 3 asasa 

這裏是一個進一步的測試在兩個額外行,而在C1和C2對應的行。有兩個查詢測試,我的和querydkkumargoyal

CREATE TABLE A(main_key INTEGER NOT NULL PRIMARY KEY, stuff_id INTEGER NOT NULL); 
INSERT INTO A VALUES(1, 7); 
INSERT INTO A VALUES(2, 6); 
INSERT INTO A VALUES(3, 3); 
INSERT INTO A VALUES(4, 3); 
INSERT INTO A VALUES(5, 3); 

CREATE TABLE MC(category_id INTEGER NOT NULL PRIMARY KEY, category_name VARCHAR(10) NOT NULL); 
INSERT INTO mc VALUES(1, "blablbl"); 
INSERT INTO mc VALUES(2, "asas"); 
INSERT INTO mc VALUES(3, "asasa"); 

CREATE TABLE C1(category_id INTEGER NOT NULL REFERENCES mc, main_key INTEGER NOT NULL REFERENCES a); 
INSERT INTO c1 VALUES(1, 1); 
INSERT INTO c1 VALUES(1, 2); 
INSERT INTO c1 VALUES(3, 1); 
INSERT INTO c1 VALUES(3, 4); 
INSERT INTO c1 VALUES(1, 4); 
INSERT INTO c1 VALUES(1, 5); 

CREATE TABLE C2(category_id INTEGER NOT NULL REFERENCES mc, main_key INTEGER NOT NULL REFERENCES a); 

INSERT INTO c2 VALUES(2, 3); 
INSERT INTO c2 VALUES(2, 1); 
INSERT INTO c2 VALUES(2, 5); 

SELECT COUNT(*) AS Stuff_Qnt, C.Category_ID, MC.Category_Name 
    FROM MC 
    JOIN (SELECT C1.Category_ID 
      FROM A 
      JOIN C1 ON A.Main_Key = C1.Main_Key 
     UNION ALL 
     SELECT C2.Category_ID 
      FROM A 
      JOIN C2 ON A.Main_Key = C2.Main_Key 
     ) AS C 
    ON C.Category_ID = MC.Category_ID 
GROUP BY C.Category_ID, MC.Category_Name 
ORDER BY C.Category_ID, Stuff_Qnt; 

-- Query by dkkumargoyal 
SELECT COUNT(DISTINCT A.stuff_id) AS stuff_qnt, MC.category_id, MC.category_name 
FROM A 
LEFT JOIN C1 on a.main_key = c1.main_key -- USING(main_key) 
LEFT JOIN C2 on a.main_key = c2.main_key -- USING(main_key) 
LEFT JOIN MC ON (C1.category_id = MC.category_id OR C2.category_id = MC.category_id) 
GROUP BY MC.category_id, mc.category_name 
ORDER BY MC.Category_id, stuff_qnt;  -- stuff_qnt added for standard compatibility 

所做的更改對代碼在測試DBMS(Informix 11.70.FC6)上工作是必需的。

結果1:

4 1 blablbl 
3 2 asas 
2 3 asasa 

結果2:

3 1 blablbl 
2 2 asas 
2 3 asasa 

我認爲我的結果是正確的,其他沒有,主要是因爲可供選擇取決於當問題規定,它A.Stuff_ID是唯一不是唯一的(並且額外的數據行使其不唯一)。

+0

您如何看待'bonCodigo'的查詢?並感謝你的幫助,我只是在想哪一個更好,他的查詢速度有點快(我猜是因爲連接數少了)。只是有趣的你的想法。謝謝。 – user1016265

+0

他的查詢與我的非常相似;他做了一個更簡單的(未加入)聯盟 - 它可以說比我的重複加入者更加整潔。一個非常好的優化器可能會等價地對待這兩個。這是一個很好的重組;如果我花了很長時間來研究它,我可能也會這樣做。這是DRY(不要重複自己)原理的簡單應用。他的回答指出了一種方法來簡化你的生活;放棄兩個類別表;只使用一個。 –

0

試試這個SQL。

SELECT COUNT(DISTINCT A.stuff_id) AS stuff_qnt, MC.category_id, MC.category_name 
FROM A 
LEFT JOIN C1 USING(main_key) 
LEFT JOIN C2 USING(main_key) 
LEFT JOIN MC ON (C1.category_id = MC.category_id OR C2.category_id = MC.category_id) 
GROUP BY MC.category_id 
+0

在樣本數據上,這會產生所需的結果。但是,如果您使用以下方法擴充樣本數據:'INSERT INTO A VALUES(4,3); 插入一個值(5,3);插入c1值(3,4); 插入c1值(1,4);插入c1值(1,5); INSERT INTO C2數值(2,5);',那麼這個查詢產生從礦井不同的結果,因爲它依賴於'A.Stuff_ID'是唯一的時,問題規定,它不是(和附加數據使得非獨特)。 –

+0

@JonathanLeffler你的SQL賦予不同的A.main_key的數量。這可以通過使用count從我的查詢中輕鬆實現(distinct A.main_key)。但是,哪些查詢是寫入取決於user1016265想要的結果。我的猜測是基於在問題中選擇的coulum。 – dkkumargoyal

1

請看一看這個參考:

查詢:

select m.category_id, m.category_name, count(a.stuff_id) as cntstuff from 
(select * from c1 
union all 
select * from c2) as c 
join a 
on a.main_key = c.main_key 
join mc m 
on m.category_id = c.category_id 
group by m.category_id 
order by m.category_id 
; 

結果:

CATEGORY_ID  CATEGORY_NAME CNTSTUFF 
1    blablbl   2 
2    asas   2 
3    asasa   1