簡體   English   中英

SQL兩個一對多關系-計數記錄

[英]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`

這與feedCommentfeedLike 分開使用 如果我嘗試同時使用它們,則無法正常工作。

我該怎么做?

為什么不使用子查詢? (至少可以在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行feedLikefeedComment中的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM