使用联接表中的条件获取COUNT

时间:2017-11-28 15:22:01

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

我有一张表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

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

4 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:1)

您只需要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 BY和{的第一列中更改查询的那一部分{1}}。

答案 2 :(得分:1)

另一种解决方案。我希望它能奏效 - 没有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

答案 3 :(得分:0)

我希望子查询不被禁止:

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