Как включить названия месяцев с количеством 0 для ежемесячного подсчета данных? - PullRequest
0 голосов
/ 15 февраля 2019

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

SELECT dateName(month,tn.processstarttime) as reqMonth, count(ID) as requestCount, year(tn.processstarttime) as reqYear
FROM table A tn WHERE  year(tn.processstarttime) in (year(DATEADD(MONTH, 0, GETDATE())),year(DATEADD(MONTH, -12, GETDATE()))) 
AND tn.processstarttime>DATEADD(MONTH, -12, GETDATE()) 
GROUP BY dateName(month,tn.processstarttime),year(tn.processstarttime)
order by dateName(month,tn.processstarttime),year(tn.processstarttime)

Но этот запрос не дает названия месяцев, для которых счетчик данных равен 0.

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

Спасибо

Ответы [ 3 ]

0 голосов
/ 15 февраля 2019

Стандартным способом является использование таблицы календаря со всеми необходимыми годами и месяцами, а затем LEFT JOIN для вашего результата.Если в вашей таблице не будет соответствующей записи для какого-либо месяца, вы будете использовать COALESCE для получения 0 за эти месяцы.Смотрите запрос ниже (я использовал CTE для получения календарной таблицы, IMO самый простой способ):

;with MonthNames as (
    select 1 MonthNo, 'January' MonthName
    union all
    select 2, 'February'
    union all
    select 3, 'March'
    union all
    select 4, 'April'
    union all
    select 5, 'May'
    union all
    select 6, 'June'
    union all
    select 7, 'July'
    union all
    select 8, 'August'
    union all
    select 9, 'September'
    union all
    select 10, 'October'
    union all
    select 11, 'November'
    union all
    select 12, 'December'
), Years as (
    select 2017 Year union all select 2018 union all select 2019
), CalendarTable as (
    select * from MonthNames cross join Years
)

select ct.MonthName,
       ct.Year,
       COALESCE(t.requestCount, 0) requestCount
from CalendarTable ct
left join (YOUR WHOLE SELECT) t
on t.Year = ct.Year and t.month = ct.MonthNo
0 голосов
/ 15 февраля 2019

Этот ответ может быть аналогичен ответу Михала Турчина, но есть несколько существенных отличий:

Не обращайте особого внимания на различия, создающие первые два CTE, так как разные они выглядят как неактуальные, просто материальностилей.

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

Не актуально, но также важно, чтобы он покрывал «ежемесячные данные».считать за прошлый год до текущего месяца "Требование заказа на поставку без жестких кодов, оно может быть в представлении или функции, которую не нужно изменять год за годом ...

WITH months AS (
        SELECT 1 AS MonthNum, DATENAME(Month,DATEFROMPARTS(1,1,1)) AS MonthName
        UNION ALL
        SELECT MonthNum + 1, DATENAME(Month,DATEFROMPARTS(1, MonthNum + 1, 1)) AS MonthName
        FROM months
        WHERE MonthNum <= 11
    ),
    years as (
        SELECT YEAR(GETDATE())-1 AS Year
        UNION ALL
        SELECT Year + 1
        FROM years 
        WHERE Year + 1 <= YEAR(GETDATE())
    ),
    dates as (
        SELECT Year, MonthNum, MonthName, DATEFROMPARTS(Year, MonthNum, 1) AS DateStart, DATEADD(MONTH, 1, DATEFROMPARTS(Year, MonthNum, 1)) AS DateEnd
        FROM years
        CROSS JOIN months
    )
    SELECT D.Year, D.MonthNum, D.MonthName, COUNT(ID) AS RequesCount
    FROM dates D
    LEFT JOIN  YourTable A ON A.ProcessStartTime >= DateStart AND A.ProcessStartTime < DateEnd
    WHERE DateStart < GETDATE()
    GROUP BY D.Year, D.MonthNum, D.MonthName
    ORDER BY Year, MonthNum
0 голосов
/ 15 февраля 2019

Попробуйте это

SELECT months.month_name AS reqMonth, COUNT(ID) AS requestCount, YEAR(tn.processstarttime) AS reqYear
FROM A tn
    RIGHT JOIN (VALUES ('january'),('february'),('march'),('april'),
                       ('may'),('june'),('july'),('august'),('september'),
                       ('october'),('november'),('december')) as months(month_name) 
                ON DATENAME(month,tn.processstarttime) = months.month_name
                AND YEAR(tn.processstarttime) in (YEAR(DATEADD(MONTH, 0, GETDATE())),year(DATEADD(MONTH, -12, GETDATE()))) 
                AND tn.processstarttime>DATEADD(MONTH, -12, GETDATE()) 
GROUP BY months.month_name,YEAR(tn.processstarttime)
order by months.month_name,YEAR(tn.processstarttime)

В действии здесь

...