简体   繁体   English

SQL查询计数出现的次数,然后按天分组,但也填写缺少的日子

[英]SQL query count occurrences then group by day but also fill missing days

I have a table called diseaseScores which has calculation results. 我有一个名为diseaseScores的表,该表具有计算结果。 Each hour a running score is calculated ( currentScore ). 每小时计算一次跑步成绩( currentScore )。 The objective of this query is to group the hourly scores by the day ( obsDate ), then count the numberOfhours where the running score is at a level considered high. 该查询的目的是按小时( obsDate )将小时分数obsDate ,然后计算跑步分数处于较高水平的numberOfhours High is greater than 16 ( currentScore > 16 ). 高大于16( currentScore > 16 )。

My query so far is: 到目前为止,我的查询是:

SELECT
    DATEADD(DAY, 0, DATEDIFF(day, 0, obsDate)) AS obsDate, 
    (CASE 
        WHEN count(id) > 12 THEN count(id) 
        ELSE 0 
     END) numOfHoursAtHigh 
FROM
    diseaseScores
WHERE 
    diseaseID = 2 
    AND siteID = 72160 
    AND numOfRotationYears = 3 
    AND currentScore > 16 
    AND month(obsDate) IN (6) 
GROUP BY
    DATEADD(DAY, 0, DATEDIFF(day, 0, obsDate)) 
ORDER BY
    DATEADD(DAY, 0, DATEDIFF(day, 0, obsDate));

The query returns results for 13 days of the month. 该查询返回每月13天的结果。 I wish to fill the gaps so I a have a record for each of the day of the month. 我希望填补空白,所以我每个月的每一天都有一个记录。 The gaps need to have a numOfHoursAtHigh result of 0. 间隙需要将numOfHoursAtHigh结果numOfHoursAtHigh 0。

How can I do this? 我怎样才能做到这一点? This is for SQL Server 2008 + 这是针对SQL Server 2008 +

The result set being returned is: 返回的结果集为:

        2016-06-04 00:00:00.000     0
        2016-06-05 00:00:00.000     23
        2016-06-06 00:00:00.000     23
        2016-06-07 00:00:00.000     23
        2016-06-08 00:00:00.000     3
        2016-06-09 00:00:00.000     23
        2016-06-10 00:00:00.000     0
        2016-06-17 00:00:00.000     13
        2016-06-18 00:00:00.000     23
        2016-06-19 00:00:00.000     0
        2016-06-20 00:00:00.000     14
        2016-06-21 00:00:00.000     23
        2016-06-22 00:00:00.000     16

UPDATE : So using a modified version of knobcreekmans approach (was doubling up certain days) I now have this which does fill my gaps and works great for one month. 更新:因此,使用经过修改的旋钮式方法(在某些日子里翻了一番),我现在有了这个方法,它确实填补了我的空白,并且可以工作一个月。 As soon as I ask for two months worth by changing month(obsDate) IN (6) to month(obsDate) IN (6,7) it skips days if they happen to clash in month 6 and 7. Grrrrrr, am so close! 一旦我通过将month(obsDate)IN(6)更改为month(obsDate)IN(6,7)来要求两个月的价值,如果它们恰好在第6和第7个月发生冲突,它就会跳过几天。

        SELECT CAST(obsDate AS DATE) as obsDate, 
            (CASE 
                WHEN COUNT(id) > 12 THEN COUNT(id) 
                ELSE 0 
              END) numOfHoursAtHigh 
        FROM diseaseScores
        WHERE diseaseID=2 
           AND siteID=72160 
           AND numOfRotationYears=3 
           AND currentScore > 16 
           AND month(obsDate) IN (6) 
          GROUP BY CAST(obsDate AS DATE) 
        UNION
        SELECT CAST(obsDate AS DATE) AS obsDate, 
            0 AS numOfHoursAtHigh 
        FROM diseaseScores
        WHERE diseaseID=2 
           AND siteID=72160 
           AND numOfRotationYears=3 
           AND currentScore <= 17       
           AND month(obsDate) IN (6)
           and day(obsDate) NOT IN      --<-- added from here
           (
        SELECT distinct day(obsDate) 
        FROM diseaseScores
        WHERE diseaseID=2 
           AND siteID=72160 
           AND numOfRotationYears=3 
           AND currentScore > 16 
           AND month(obsDate) IN (6) 
           )                           --<-- to here to omit the duplicates
        GROUP BY CAST(obsDate AS DATE)
        ORDER BY CAST(obsDate AS DATE)  

To answer to the question around the expected result. 围绕预期结果回答问题。 Its one record for each day of the month (or months) giving to columns. 每个月(或几个月)每天的一个记录。 A date and then an integer for numOfHoursAtHigh eg 日期,然后是numOfHoursAtHigh的整数,例如

        2016-06-01  0
        2016-06-02  0
        2016-06-03  0
        2016-06-04  0
        2016-06-05  23
        2016-06-06  23
        2016-06-07  23
        2016-06-08  23
        2016-06-09  23
        2016-06-10  0
        2016-06-11  0
        2016-06-12  0
        2016-06-13  0
        2016-06-14  0
        2016-06-15  0
        2016-06-16  0
        2016-06-17  13
        2016-06-18  23
        2016-06-19  0
        2016-06-20  14
        2016-06-21  23
        2016-06-22  16
        2016-06-23  0
        2016-06-24  0
        2016-06-25  0
        2016-06-26  0
        2016-06-27  0
        2016-06-28  0
        2016-06-29  0
        2016-06-30  0

You could create another SELECT that is the same as the original, modify the part of your WHERE clause that is filtering out the results you want ( currentScore > 16 ), and then UNION them together. 你可以创建另一个SELECT就是将原来一样,修改的部分WHERE被过滤掉你想要的结果(第currentScore > 16 ),然后UNION在一起。

SELECT CAST(obsDate AS DATE) as obsDate, 
    (CASE 
        WHEN COUNT(id) > 12 THEN COUNT(id) 
        ELSE 0 
      END) numOfHoursAtHigh 
FROM diseaseScores
WHERE diseaseID=2 
   AND siteID=72160 
   AND numOfRotationYears=3 
   AND currentScore > 16 
   AND month(obsDate) IN (6) 
  GROUP BY CAST(obsDate AS DATE) 
UNION
SELECT CAST(obsDate AS DATE) AS obsDate, 
    0 AS numOfHoursAtHigh 
FROM diseaseScores
WHERE diseaseID=2 
   AND siteID=72160 
   AND numOfRotationYears=3 
   AND currentScore < 17       --<-- note the change
   AND month(obsDate) IN (6) 
GROUP BY CAST(obsDate AS DATE)
ORDER BY CAST(obsDate AS DATE)


Hi, 你好
You can have the below query, 您可以进行以下查询,

SELECT  DS.dateadd(DAY,0, datediff(day,0, obsDate)) as obsDate,
CASE 
WHEN  DS1.COUNT(id) > 12 THEN COUNT(id)
ELSE 0
END AS numOfHoursAtHigh
  FROM diseaseScores DS
  INNER JOIN (
SELECT dateadd(DAY,0, datediff(day,0, obsDate)) AS date, COUNT(id)
FROM diseaseScores GROUP BY  date
) DS1
ON DS.date = DS1.obsDate
AND DS.diseaseID=2 
AND DS.siteID=721DS.60 
AND DS.numOfRotationYears=3 
AND DS.currentScore > 16 
AND DS.month(obsDate) IN (6) 
ORDER BY DS.obsDate;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM