2017-07-13 59 views
1

我想要計算行數,或者在此情況下是同一類別中的產品數量,如果類別中沒有產品,則返回零。MySQL計算聯合表中的行

在我的查詢中的表看起來像這樣:

category     category_lang     media 
------------    -------------     --------- 
category_id | published  category_id | name | alias media_id | category_id 
-----------------------  -------------------------- ---------------------- 
1   | 1   1   | One | one  1  | 1 
2   | 1   2   | Two | two  2  | 2 
3   | 1   3   | Three| three 3  | 3 

media_lang       product_category 
-------------------------------  ---------------- 
media_id | url  | file_name  product_id | category_id 
-------------------------------  ------------------------ 
1  | /images/ | file1.jpg  1   | 1 
2  | /images/ | file2.jpg  2   | 1 
3  | /images/ | file3.jpg  3   | 2 

,我想這樣的結果:

category_id | category_name | alias | media_id | url  | file_name | count 
1   | One   | one | 1  | /images/ | file1.jpg | 2 
2   | Two   | two | 2  | /images/ | file2.jpg | 1 
3   | Three   | three | 3  | /images/ | file3.jpg | 0 

我的查詢目前看起來像這樣

SELECT 
c.`category_id`, 
ca.`name`, 
ca.`alias`, 
m.`media_id`, 
ma.`url`, 
ma.`file_name`, 
COUNT(p.`product_id`) AS `count` 
FROM `category` c 
LEFT JOIN `category_lang` ca ON (c.`category_id` = ca.`category_id`) 
LEFT JOIN `media` m ON (c.`category_id` = m.`category_id`) 
LEFT JOIN `media_lang` ma ON (m.`media_id` = ma.`media_id`) 
LEFT JOIN `product_category` p ON (c.`category_id` = p.`category_id`) 
WHERE c.`published` = 1 
ORDER BY ca.`name` 

我邏輯顯然是錯誤的,因爲這個查詢將返回這個:

category_id | category_name | alias | media_id | url  | file_name | count 
1   | One   | one | 1  | /images/ | file1.jpg | 3 

我該如何達到預期的效果?

+0

更改'COUNT(p.product_id)AS計數到COUNT(不同的p.product_id)AS計數'問題是您的計數被一個連接人爲地誇大了,每個連接有多個記錄。 – xQbert

+1

對於我的生活,我不明白你是如何得到這些數字。從我所看到的情況來看,所有計數都應該是1,並且在結果集中只應該有三條記錄,甚至不會加上COUNT()。順便說一句,你應該用'COUNT'來使用'GROUP BY',但是你的預期輸出對我來說沒有意義。 –

+0

@Tim Biegeleisen再看一眼。第一類有2個產品,第二類有1,第三類有零, –

回答

1

我認爲解決這個最無痛的(和理智)的方式是隻聚集的產品數爲每個類別從PRODUCT_CATEGORY表在一個單獨的子查詢,然後快快加入這你已經擁有:

SELECT 
    c.category_id, 
    ca.name, 
    ca.alias, 
    m.media_id, 
    ma.url, 
    ma.file_name, 
    COALESCE(t.cat_count, 0) AS cat_count 
FROM category c 
LEFT JOIN category_lang ca 
    ON c.category_id = ca.category_id 
LEFT JOIN media m 
    ON c.category_id = m.category_id 
LEFT JOIN media_lang ma 
    ON m.media_id = ma.media_id 
LEFT JOIN 
(
    SELECT category_id, COUNT(*) AS cat_count 
    FROM product_category 
    GROUP BY category_id 
) t 
    ON c.category_id = t.category_id 
WHERE c.published = 1 
ORDER BY ca.name 

注意這裏,你product_category表沒有,沒有任何產品類別條目。這不是問題,因爲在LEFT JOIN中,我們可以簡單地將NULL計數視爲零。如果給定類別與子查詢中的任何內容不匹配,則會發生值NULL

+0

謝謝。這是一個很好的解決方案,它的工作。看看你的第一條評論我認爲你已經發布瞭解決方案:)將「GROUP BY c.category_id」添加到我原來的查詢中,得出的結果與你的結果相同。你的答案是一個很好的教學例子。 –

+0

@LaciK小心:只要將'GROUP BY c.category_id'添加到您的原始查詢中,就會導致無效的SQL,甚至無法在某些MySQL配置上運行(並且根本不在SQL Server,Oracle等上)。一般來說,你不能只彙總這種方式。 –

0

在我看來,它是你在做計數的地方,而且你有做計數的標準。在產品類別ID等於類別表中的類別ID時添加額外條件應修復不正確的計數。

SELECT 
c.`category_id`, 
ca.`name`, 
ca.`alias`, 
m.`media_id`, 
ma.`url`, 
ma.`file_name`, 
COUNT(p.`product_id`) AS `count` 
FROM `category` c 
LEFT JOIN `category_lang` ca ON (c.`category_id` = ca.`category_id`) 
LEFT JOIN `media` m ON (c.`category_id` = m.`category_id`) 
LEFT JOIN `media_lang` ma ON (m.`media_id` = ma.`media_id`) 
LEFT JOIN `product_category` p ON (c.`category_id` = p.`category_id`) 
WHERE (c.`published` = 1) and (c.`category_id` = p.`category_id`) 
ORDER BY ca.`name` 
+0

我可能是錯的,但對我來說,你的語法看起來不對。我在FROM之後加上count會觸發語法錯誤。 –

+0

你說得對。我把它粘在錯誤的地方。 TYVM捕捉它。 –