【问题标题】:Get COUNT with a condition from a joined table从联接表中获取带有条件的 COUNT
【发布时间】:2017-11-28 15:22:01
【问题描述】:

我有一张桌子SyncHistory

SyncHistoryId     SyncType     SyncDateTime
-----------------------------------------------------
    55              1       2017-11-28 09:30:51.810
    56              1       2017-11-28 10:30:32.123

然后是另一张桌子SyncDetails

SyndDetailId      SyncHistoryId     ItemId     ItemCreated     ItemChanged
---------------------------------------------------------------------------
    98                 55           12345          1                 0
    99                 55           23183          1                 0
    100                55           87687          0                 1
    101                55           23234          0                 0
    102                55           23222          0                 0
    103                56           9928           1                 0

我想做的是创建一个查询,它给我这个:

Sync Data              New          Existing & Changed   Existing & Not Changed
---------------------------------------------------------------------------
11/28/2017 9:30am       2                 1                    2    
11/28/2017 10:30am      1                 0                    0

这就是我正在尝试的:

SELECT 
    sh.SyncHistoryId
    , sh.SyncDateTime
    , count(sd1.SyncDetailId) AS Created
    , count(sd2.SyncDetailId) AS ExistingChanged
    , count(sd3.SyncDetailId) AS ExistingNotChanged
FROM
    SyncHistory sh
    LEFT JOIN SyncDetails sd1 ON sh.SyncHistoryId = sd1.SyncHistoryId AND sd1.ItemCreated = 1 AND sd1.ItemChanged = 0
    LEFT JOIN SyncDetails sd2 ON sh.SyncHistoryId = sd2.SyncHistoryId AND sd2.ItemCreated = 0 AND sd2.ItemChanged = 1
    LEFT JOIN SyncDetails sd3 ON sh.SyncHistoryId = sd3.SyncHistoryId AND sd3.ItemCreated = 0 AND sd3.ItemChanged = 0
WHERE
    sh.SyncType = 1
GROUP BY
    sh.SyncHistoryId
    , sh.SyncDateTime
ORDER BY
    sh.SyncDateTime DESC

但是,结果计数都不准确。我做错了什么,但不确定是什么。

【问题讨论】:

  • 请准备演示,同样按SyncDateTime分组没有意义,可能你想按整小时分组/
  • 如果我没有那个 GroupBy,查询会抛出错误
  • 另外,如何准备演示?有没有在线sql演示工具?
  • 当然你可以使用rextester.comdbfiddle.uk 只需粘贴create table + insert into and share link here。
  • 还有 sqlfiddle.com

标签: sql sql-server tsql sql-server-2016


【解决方案1】:
SELECT h.SyncDateTime, 
       SUM(case when d.ItemCreated = 1 then 1 else 0 end) as New,
       SUM(case when d.ItemChanged = 1 then 1 else 0 end) as [Existing & Changed],
       SUM(case when d.ItemCreated  = 0 and d.ItemChanged  = 0 then 1 else 0 end) as [Existing & Not Changed]
FROM   SyncHistory h
       INNER JOIN SyncDetails d ON h.SyncHistoryId = d.SyncHistoryId     
GROUP BY h.SyncDateTime

【讨论】:

    【解决方案2】:

    您只需JOIN 到详细信息表一次。您可以通过聚合从中获得计数:

    SELECT
        CONVERT(VARCHAR(16), SH.SyncDateTime, 120) AS SyncTime,
        SUM(CASE WHEN SD.ItemCreated = 1 AND SD.ItemChanged = 0 THEN 1 ELSE 0 END) AS New,
        SUM(CASE WHEN SD.ItemCreated = 0 AND SD.ItemChanged = 1 THEN 1 ELSE 0 END) AS ExistingAndChanged,
        SUM(CASE WHEN SD.ItemCreated = 0 AND SD.ItemChanged = 0 THEN 1 ELSE 0 END) AS ExistingAndNotChanged
    FROM
        SyncHistory SH
    LEFT OUTER JOIN SyncDetails SD ON SD.SyncHistoryID = SH.SyncHistoryID
    GROUP BY
        CONVERT(VARCHAR(16), SH.SyncDateTime, 120)
    

    您不清楚应该如何确定分组/日期时间。我所拥有的是分分钟。如果它应该是按 1/2 小时标记的小时或其他时间,那么您需要更改 GROUP BYSELECT 的第一列中的查询部分。

    【讨论】:

      【解决方案3】:

      另一种解决方案。我希望它会起作用 - 没有CASE,没有子查询:

      SELECT 
          sh.SyncHistoryId
          ,sh.SyncDateTime
          ,COUNT( NULLIF( sd.ItemCreated, 0 ) ) AS Created
          ,COUNT( NULLIF( sd.ItemCreated, 1 ) + NULLIF( sd1.ItemChanged, 0 ) ) AS ExistingChanged
          ,COUNT( NULLIF( sd.ItemCreated, 1 ) + NULLIF( sd1.ItemChanged, 1 ) ) AS ExistingNotChanged
      FROM
          SyncHistory sh JOIN SyncDetails sd ON sh.SyncHistoryId = sd.SyncHistoryId
      WHERE
          sh.SyncType = 1
      GROUP BY
          sh.SyncHistoryId
          ,sh.SyncDateTime
      
      ORDER BY
          sh.SyncDateTime DESC
      

      【讨论】:

        【解决方案4】:

        我希望子查询不被禁止:

        SELECT 
            sh.SyncHistoryId
            ,sh.SyncDateTime
            ,(SELECT COUNT(*) FROM SyncDetails sd WHERE sh.SyncHistoryId = sd.SyncHistoryId AND sd.ItemCreated = 1 AND sd1.ItemChanged = 0) AS Created
            ,(SELECT COUNT(*) FROM SyncDetails sd WHERE sh.SyncHistoryId = sd.SyncHistoryId AND sd.ItemCreated = 0 AND sd1.ItemChanged = 1) AS ExistingChanged
            ,(SELECT COUNT(*) FROM SyncDetails sd WHERE sh.SyncHistoryId = sd.SyncHistoryId AND sd.ItemCreated = 0 AND sd1.ItemChanged = 0) AS ExistingNotChanged
        FROM
            SyncHistory sh
        WHERE
            sh.SyncType = 1
        ORDER BY
            sh.SyncDateTime DESC
        

        【讨论】:

        • 好的,我在想这个解决方案可能会很慢。我尽量避免 SELECT 中的子查询
        • 你还认为这里需要GROUP BY
        • @NiranjanRajawat 好的,没有 GROUP BY。我在 WHERE 之后复制了查询的结尾。
        猜你喜欢
        • 1970-01-01
        • 2017-07-30
        • 1970-01-01
        • 1970-01-01
        • 2021-03-29
        • 1970-01-01
        • 2012-10-17
        • 2014-01-30
        • 2022-08-07
        相关资源
        最近更新 更多