[英]MySQL Join three tables return multiple results
我有三個表:我們稱其為CUSTOMER,LOG和REVIEW
客戶表為:
id name
== ====
1 John
2 Jane
3 Mike
LOG表是
id customer_id created_at
== =========== ==========
1 1 2015-06-10
2 1 2015-06-10
3 2 2015-06-11
4 1 2015-06-13
5 2 2015-06-15
6 1 2015-06-15
REVIEW表是
id customer_id created_at
== =========== ==========
1 1 2015-06-10
2 2 2015-06-10
3 2 2015-06-11
4 1 2015-06-13
5 1 2015-06-15
6 1 2015-06-15
7 1 2015-06-18
我想要什么
CUSTOMER_ID NAME LOG_QTY REVIEW_QTY
=========== ==== ======= ==========
1 John 4 5
2 Jane 2 2
3 Mike 0 0
我得到了:
CUSTOMER_ID NAME LOG_QTY REVIEW_QTY
=========== ==== ======= ==========
1 John 20 20
2 Jane 4 4
3 Mike 0 0
我的查詢:
select CUSTOMER.ID, CUSTOMER.NAME,
count(REVIEW.CUSTOMER_ID) as REVIEW_QTY,
count(LOG.CUSTOMER_ID) as LOG_QTY
from CUSTOMER
left join REVIEW
on REVIEW.CUSTOMER_ID = CUSTOMER.ID
left join LOG
on LOG.CUSTOMER_ID = CUSTOMER.ID
group by CUSTOMER.ID
order by CUSTOMER.ID
您的查詢正在做的是加入評論並登錄客戶,而兩者之間沒有加入條件。 這意味着您將使用給定客戶的每個評論來創建每個日志的笛卡爾乘積(例如,您希望John獲得的4條日志乘以他的5條評論就可以得到20條)。
解決此問題的一種方法是在子查詢中分別對日志和評論進行group by
:
SELECT c.id, c.name, review_qty, log_qty
FROM customer c
LEFT JOIN (SELECT customer_id, COUNT(*) AS review_qty
FROM review
GROUP BY customer_id) r ON r.customer_id = c.id
LEFT JOIN (SELECT customer_id, COUNT(*) AS log_qty
FROM log
GROUP BY customer_id) l ON l.customer_id = c.id
ORDER BY c.id
如果您在沒有COUNT()
和GROUP BY
情況下運行查詢,則會看到發生了什么:
select CUSTOMER.ID, CUSTOMER.NAME,
REVIEW.CUSTOMER_ID as REVIEW_QTY,
LOG.CUSTOMER_ID as LOG_QTY
from CUSTOMER
left join REVIEW on REVIEW.CUSTOMER_ID = CUSTOMER.ID
left join LOG on LOG.CUSTOMER_ID = CUSTOMER.ID
order by CUSTOMER.ID
這將為三個表中具有相同CUSTOMER_ID
的行的每個可能組合返回一行(這就是INNER JOIN
所做的事情)。 然后COUNT
只算一次!
這應該給您您需要的:
select CUSTOMER.ID, CUSTOMER.NAME,
(select count(*) from REVIEW where CUSTOMER_ID = CUSTOMER.ID) as REVIEW_QTY,
(select count(*) from LOG where CUSTOMER_ID = CUSTOMER.ID) as LOG_QTY
from CUSTOMER
order by CUSTOMER.ID
每當您遇到這樣的復雜查詢時,我總是建議您先將其分解成幾部分,然后再放回去。
例如,要獲取單個表的每個客戶的計數,可以使用以下聚合:
SELECT customer_id, COUNT(*) AS logCount
FROM log
GROUP BY customer_id;
您可以進行同樣的操作以進行審查,最后,將這些結果外聯到customer表以獲取其名稱。 您應該使用外部聯接的原因是因為用戶可能在其他表中沒有任何條目。 因此,您應該使用COALESCE()
函數將空計數替換為0:
SELECT c.id, c.name, COALESCE(l.logCount, 0) AS logCount, COALESCE(r.reviewCount, 0) AS reviewCount
FROM customer c
LEFT JOIN(
SELECT customer_id, COUNT(*) AS logCount
FROM log
GROUP BY customer_id) l ON l.customer_id = c.id
LEFT JOIN(
SELECT customer_id, COUNT(*) AS reviewCount
FROM review
GROUP BY customer_id) r ON r.customer_id = c.id;
這是一個使用示例數據的SQL Fiddle示例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.