[英]SQL two one-to-many relations - count records
我有一個feed
表, feedComment
表和feedLike
表。
我需要在一個查詢中,從數據庫中選擇所有帶有評論和喜歡數的提要。
這是我到目前為止的內容:
SELECT
`feed`.`id` AS `feedID`,
`feed`.`companyID`,
`feed`.`eventID`,
`feed`.`memberID` AS `personID`,
`feed`.`title`,
`feed`.`text`,
`feed`.`shares`,
UNIX_TIMESTAMP(`feed`.`date`) AS `date`,
COUNT(`feedComment`.`id`) AS `comments`
FROM `feed`
LEFT JOIN `feedComment`
ON `feedComment`.`feedID` = `feed`.`id`
GROUP BY `feed`.`id`
這與feedComment
和feedLike
分開使用 。 如果我嘗試同時使用它們,則無法正常工作。
我該怎么做?
為什么不使用子查詢? (至少可以在Sql Server上運行)
Select `feed`.`id` AS `feedID`,
`feed`.`companyID`,
`feed`.`eventID`,
`feed`.`memberID` AS `personID`,
`feed`.`title`,
`feed`.`text`,
`feed`.`shares`,
UNIX_TIMESTAMP(`feed`.`date`) AS `date`,
(Select count(`feedComment`.`id`) from feedComment Where commentid = F.id) as 'Comment',
(Select count('feedLike'.'id') from feedLike Where likeid = F.id) as 'Something else'
From feed F
如果您只需要計數,我不明白為什么使用join
鑒於目前為止,您可以添加一個內聯視圖以從feedLike
返回計數。
SELECT `feed`.`id` AS `feedID`,
`feed`.`companyID`,
`feed`.`eventID`,
`feed`.`memberID` AS `personID`,
`feed`.`title`,
`feed`.`text`,
`feed`.`shares`,
UNIX_TIMESTAMP(`feed`.`date`) AS `date`,
IFNULL(`countLike`.`cnt`,0) AS `likes`,
COUNT(`feedComment`.`id`) AS `comments`
FROM `feed`
LEFT
JOIN `feedComment`
ON `feedComment`.`feedID` = `feed`.`id`
-- outer join to inline view (MySQL derived table)
LEFT
JOIN (
SELECT `feedLike`.`feedID`
, COUNT(`feedLike`.`id`) AS `cnt`
FROM `feedLike`
GROUP BY `feedLike`.`feedID`
) `countLike`
ON `countLike`.`feedID` = `feed`.`id`
GROUP BY `feed`.`id`
將執行括號之間的查詢,其結果將是MySQL稱為“派生表”的內容。 我們為該派生表分配一個名稱... countLike
。 對於外部查詢,就像countLike
是一個實際表一樣。
外部選擇中使用IFNULL()
函數將可能的NULL值替換為零。 這不是強制性的,但是通常人們喜歡將“零”作為計數返回,而不是NULL。
請注意,派生表可能存在嚴重的性能問題。 (MySQL的最新版本解決了其中的一些問題,例如派生表上沒有索引。)
同樣的方法也可以應用於從feedComment
表中獲取計數。 特別是如果沒有其他需要按feed.id
。
SELECT feed.id AS `feedID`
, feed.companyID
, feed.eventID
, feed.memberID AS `personID`
, feed.title
, feed.text
, feed.shares
, UNIX_TIMESTAMP(feed.date) AS `date`
, IFNULL(countLike.cnt,0) AS `likes`
, IFNULL(countComment.cnt,0) AS `comments`
FROM feed
LEFT
JOIN ( SELECT c.feedID
, COUNT(1) AS cnt
FROM feedComment c
GROUP BY c.feedID
) countComment
ON countComment.feedID = feed.id
LEFT
JOIN ( SELECT l.feedID
, COUNT(1) AS cnt
FROM feedLike l
GROUP BY l.feedID
) countLike
ON countLike.feedID = feed.id
不同
作為一個完全不同的方法,你可以有一個查詢生成部分跨產品(從每一行FeedLike
對於給定feedID匹配,從每一行FeedComment
),再算上“獨特” id
值。 但是這種方法有可能產生相當大的中間結果(並殺死性能)。 (如果給定的feed
具有30行feedLike
和feedComment
中的30行,則單個Feed的總數為1 x 30 x 30 = 900行。
我故意使此示例不完整,以防止這樣做是普遍現象。 但我將其包括在內,因為它確實展示了另一種方法:
SELECT feed.id
, ...
, COUNT(DISTINCT feedLike.ID)
, COUNT(DISTINCT feedComment.ID)
FROM feed
LEFT
JOIN feedLike
ON ...
LEFT
JOIN feedComment
ON ...
GROUP BY feed.id
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.