SQL-запрос месяц за месяцем по системе - PullRequest
1 голос
/ 03 апреля 2019

Я настраиваю отчет для системных сбоев.В отчете должны быть указаны системные сбои по системам за каждый месяц года, даже если нет сбоев, я все еще хочу 0.

Вот несколько работающий запрос:

with Months as (
    select dateadd(month,datediff(month,0,getdate()) - n, 0) MonthDate
    from (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11))dt(n))
SELECT  
    m.MonthDate,
    C.Name,
    Count(*) as 'Count'
from 
    Months m 
    LEFT OUTER JOIN Incident I
        on (m.MonthDate = DATEADD(MONTH, DATEDIFF(MONTH,0,i.CreatedDateTime),0))
    Inner JOIN CI C on C.RecId = I.SystemName_Valid
WHERE   
    I.CreatedDateTime >= DATEADD(MONTH,-11,GETDATE()) 
GROUP BY    
    m.MonthDate, C.Name

Результаты показывают только даты, когда имеются системные сбои.

Я ожидаю, что результат будет похож на следующий

MonthDate   Name     Count
1/1/2019    System1    0
1/1/2019    System2    0
1/1/2019    System3    0
1/1/2019    System4    0
2/1/2019    System1    0
2/1/2019    System2    0
2/1/2019    System3    0
2/1/2019    System4    1
3/1/2019    System1    1
3/1/2019    System2    0
3/1/2019    System3    0
3/1/2019    System4    0
4/1/2019    System1    0
4/1/2019    System2    0
4/1/2019    System3    0
4/1/2019    System4    0

Набор данных, который возвращается, хотя

MonthDate   Name     Count
2/1/2019    System4    1
3/1/2019    System1    1

Ответы [ 2 ]

2 голосов
/ 03 апреля 2019

Попробуйте изменить предложение FROM на:

from 
    Months m 
    CROSS JOIN dbo.CI -- you want to have a row per month per system
    LEFT OUTER JOIN dbo.Incident I -- this needs to be *outer* so that combos
                                   -- without a match are still included
      ON (m.MonthDate = DATEADD(MONTH, DATEDIFF(MONTH,0,i.CreatedDateTime),0))
      AND C.RecId = I.SystemName_Valid
      AND I.CreatedDateTime >= DATEADD(MONTH,-11,GETDATE()) -- this is redundant

Когда вы добавляете необязательную таблицу в предложение INNER / ON или предложение WHERE, вы включаете внешнее объединение (дайте мне все месяцы и включите любые строки инцидентов, когда мы находим тот, который соответствует) во внутреннем соединении (дайте мне только месяцев с соответствующими инцидентами).

Я бы также изменил это:

on (m.MonthDate = DATEADD(MONTH, DATEDIFF(MONTH,0,i.CreatedDateTime),0))

К этому:

ON i.CreatedDateTime >= m.MonthDate
AND i.CreatedDateTime < DATEADD(MONTH, 1, m.MonthDate)

Это позволит использовать существующий (или будущий) индекс с CreatedDateTime в ключе, что может быть или не быть более полезным в зависимости от того, сколько данных содержится в таблице инцидентов. Ваше текущее выражение заставит сканировать всю таблицу, потому что оно должно будет оценить вывод для каждой отдельной строки.

0 голосов
/ 03 апреля 2019

Используя то, что опубликовал Аарон, я изменил запрос, и у меня получилось, что он работает со следующим:

with Months as (
    select dateadd(month,datediff(month,0,getdate()) - n, 0) MonthDate
    from (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11))dt(n))
SELECT  
    m.MonthDate,
    CI.Name,
    (Select 
        count(*) 
    from 
        Incident I 
    where 
        i.SystemOutageIssue = 1 and I.CreatedDateTime >= m.MonthDate and 
        I.CreatedDateTime < DateAdd(day,1,EOMONTH(m.MonthDate)) and
        I.SystemName = CI.Name) as 'Count'
from 
    Months m 
    Cross JOIN CI
GROUP BY    
    m.MonthDate, CI.Name

Спасибо Аарону за вашу помощь, я раньше не использовал Cross Join, не такв любом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...