Выберите дату и количество, сгруппировать по дате - как отобразить даты с нулевым счетом? - PullRequest
0 голосов
/ 30 марта 2019
SELECT
    CAST(c.DT AS DATE) AS 'Date'
    , COUNT(p.PatternID) AS 'Count'
FROM CalendarMain c
LEFT OUTER JOIN Pattern p
    ON c.DT = p.PatternDate
INNER JOIN Result r
    ON p.PatternID = r.PatternID
INNER JOIN Detail d
    ON p.PatternID = d.PatternID
WHERE r.Type = 7
AND d.Panel = 501
AND CAST(c.DT AS DATE) 
    BETWEEN '20190101' AND '20190201'
GROUP BY CAST(c.DT AS DATE)
ORDER BY CAST(c.DT AS DATE)

Запрос выше не работает для меня.Он по-прежнему пропускает дни, когда COUNT имеет значение NULL, поскольку его c.DT.

c.DT и p.PatternDate оба представляют собой время DateTime, хотя c.DT не может быть NULL.Это на самом деле ПК для стола.Он заполняется как DateTimes для каждого дня с 2015 по 2049 год, поэтому записи за эти дни существуют.

Еще одна странная вещь, которую я заметил, заключается в том, что ничего не возвращается вообще, когда я присоединяю C.DT = p.PatternDate без CAST или CONVERT к стилю Date.Не уверен, почему, когда они оба DateTimes.

1 Ответ

0 голосов
/ 30 марта 2019

Здесь есть о чем поговорить. На данном этапе не ясно, что вы на самом деле пытаетесь посчитать. Если это число «шаблонов» в день за январь 2019 года, то:

  • Ваш МЕЖДУ также будет считать любые действия, происходящие 1 февраля,
  • Похоже, один шаблон может иметь несколько результатов, что может привести к неправильному подсчету
  • Похоже, что один шаблон может содержать несколько деталей, что может привести к неправильному подсчету
  • Если один шаблон имеет 3 допустимых результата, а также 4 детали, вы получите их перекрестный результат. Ваш счет будет 12.

Я собираюсь предположить:

  • вам нужно только различное количество шаблонов, независимо от количества деталей и результатов.
  • Вы хотите только январскую активность

--Set up some dummy data

DROP TABLE IF EXISTS #CalendarMain
SELECT cast('20190101' as datetime) as DT
INTO #CalendarMain
UNION ALL SELECT '20190102' as DT
UNION ALL SELECT '20190103' as DT
UNION ALL SELECT '20190104' as DT
UNION ALL SELECT '20190105' as DT  --etc etc
;

     DROP TABLE IF EXISTS #Pattern
   SELECT cast('1'as int)                         as PatternID
          ,cast('20190101 13:00' as datetime)     as PatternDate
     INTO #Pattern
UNION ALL SELECT 2,'20190101 14:00'
UNION ALL SELECT 3,'20190101 15:00'
UNION ALL SELECT 4,'20190104 11:00'
UNION ALL SELECT 5,'20190104 14:00'
;

     DROP TABLE IF EXISTS #Result
   SELECT cast(100 as int)                as ResultID
          ,cast(1 as int)                 as PatternID
          ,cast(7 as int)                 as [Type]
     INTO #Result
UNION ALL SELECT 101,1,7
UNION ALL SELECT 102,1,8
UNION ALL SELECT 103,1,9
UNION ALL SELECT 104,2,8
UNION ALL SELECT 105,2,7
UNION ALL SELECT 106,3,7
UNION ALL SELECT 107,3,8
UNION ALL SELECT 108,4,7
UNION ALL SELECT 109,5,7
UNION ALL SELECT 110,5,8
;

     DROP TABLE IF EXISTS #Detail
   SELECT cast(201 as int)                as DetailID
          ,cast(1 as int)                 as PatternID
          ,cast(501 as int)               as Panel
     INTO #Detail
UNION ALL SELECT 202,1,502
UNION ALL SELECT 203,1,503
UNION ALL SELECT 204,1,502
UNION ALL SELECT 205,1,502
UNION ALL SELECT 206,1,502
UNION ALL SELECT 207,2,502
UNION ALL SELECT 208,2,503
UNION ALL SELECT 209,2,502
UNION ALL SELECT 210,4,502
UNION ALL SELECT 211,4,501
;
       -- create some variables 
  DECLARE @start_date as date = '20190101';
  DECLARE @end_date   as date = '20190201'; --I assume this is an exclusive end date

   SELECT cal.DT
          ,isnull(patterns.[count],0) as [Count]
     FROM #CalendarMain cal
          LEFT JOIN (   SELECT cast(p.PatternDate as date)  as PatternDate
                               ,COUNT(DISTINCT p.PatternID) as [Count]
                          FROM #Pattern     p
                               JOIN #Result r ON p.PatternID = r.PatternID
                               JOIN #Detail d ON p.PatternID = d.PatternID
                         WHERE r.[Type] = 7
                               and d.Panel = 501
                      GROUP BY cast(p.PatternDate as date)
                    ) patterns ON cal.DT = patterns.patternDate
    WHERE cal.DT >= @start_date
          and cal.DT < @end_date  --Your code would have included 1 Feb, which I assume was unintentional.
 ORDER BY cal.DT
;
...