按年份和日期订购dt,缺少几个月

时间:2015-07-30 06:39:33

标签: sql sql-server tsql

我有一个简单的查询,它对日期数据进行分组和排序:

SELECT COUNT(*) AS Events,
       datepart(YYYY, call_date) AS YearPart,
       datepart(MM, call_date) As MonthPart,
       datename(YYYY, call_date) AS YearName,
       dateName(MM, call_date) As MonthName
FROM rm_report
GROUP BY 
    datename(year, call_date), 
    datename(month, call_date),
    datepart(year, call_date), 
    datepart(month, call_date)
ORDER BY 
    YearPart, 
    MonthPart;

问题是第一年的头两个月没有数据。因此,订购在第三个月开始,然后循环到第一个

EVENTS | YEARPART | YEARNAME | MONTHPART | MONTHNAME
3        2012       2012        3           March
6        2012       2012        4           April
6        2012       2012        5           May
6        2012       2012        6           June
6        2012       2012        7           July
6        2012       2012        8           August
6        2012       2012        9           September
6        2012       2012        10          October
6        2012       2012        11          November
6        2012       2012        12          December
6        2012       2013        1           January
6        2012       2013        2           February

如何确保如果没有事件,则分配0以便列表可以正确排序 - 这是MonthPart列中的第一个条目是" 1"并且YearPart列中的第一个条目是2012年?

我们正在使用MS SQL。

4 个答案:

答案 0 :(得分:2)

使用一列MONTHPART创建临时表/ CTE,其中包含1-12的数字。使用此表加入您的结果并将NULLS替换为零。

示例:

CREATE TABLE #temp 
  ( 
     [monthpart] INT 
  ) 

INSERT INTO #Temp (MONTHPART) Values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)

--SELECT * FROM #Temp 
SELECT [monthpart], 
       ISNULL([deptid], 0)      AS Department, 
       ISNULL(SUM([salart]), 0) AS Salary 
FROM   [DeeTest].[dbo].[employeesalary] 
       RIGHT JOIN #temp 
               ON empid = monthpart 
GROUP  BY deptid, 
          monthpart 

DROP TABLE #temp 

答案 1 :(得分:2)

您需要先生成monthyear的所有组合。然后在LEFT JOIN上执行rm_report

WITH CteTally(N) AS(
    SELECT N FROM(VALUES
        (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12)
    )t(N)
),
CteDates(YearPart, MonthPart, YearName, MonthName) AS(
    SELECT
        DATEPART(YEAR, DATEADD(MONTH, t.N - 1, DATEADD(YEAR, a.Y - 1900, 0))),
        DATEPART(MONTH, DATEADD(MONTH, t.N - 1, DATEADD(YEAR, a.Y - 1900, 0))),
        DATENAME(YEAR, DATEADD(MONTH, t.N - 1, DATEADD(YEAR, a.Y - 1900, 0))),
        DATENAME(MONTH, DATEADD(MONTH, t.N - 1, DATEADD(YEAR, a.Y - 1900, 0)))
    FROM(
        SELECT DISTINCT DATEPART(YEAR, call_date) AS Y
        FROM rm_report
    )a
    CROSS JOIN CteTally t
)
SELECT
    COUNT(r.call_date) AS Events,
    d.YearPart,
    d.MonthPart,
    d.YearName,
    d.MonthName
FROM CteDates d
LEFT JOIN rm_report r
    ON d.YearPart = DATEPART(YEAR, r.call_date)
    AND d.YearName= DATENAME(YEAR, r.call_date)
    AND d.MonthPart = DATEPART(MONTH, r.call_date)
    AND d.MonthName = DATENAME(MONTH, r.call_date)
GROUP BY
    d.YearPart, d.YearName, d.MonthPart, d.MonthName
ORDER BY
    d.YearName, d.MonthPart

答案 2 :(得分:2)

您可以按照Aaron Bertrand的建议创建一个日历表,并将查询写为:

--create Calendar table based on the max and min dates in table
DECLARE @Mincall_date DATETIME,@FromDate DATETIME, @ToDate DATETIME;
SET @Mincall_date =   ( SELECT MIN (Call_date) FROM @rm_report);
SET @FromDate= DATEADD(yy, DATEDIFF(yy,0,@Mincall_date), 0)
SET @ToDate =  ( SELECT MAX (Call_date) FROM @rm_report);


-- just the months in that period
DECLARE @Calendar TABLE( TheDate DATETIME,TheMonth INT, TheYear INT)

INSERT INTO @Calendar       
SELECT TOP (DATEDIFF(MONTH, @FromDate, @ToDate)+1)  
  TheDate  = DATEADD(MONTH, number, @FromDate), 
  TheMonth = MONTH(DATEADD(MONTH, number, @FromDate)),
  TheYear  = YEAR(DATEADD(MONTH, number, @FromDate))   
  FROM [master].dbo.spt_values   
  WHERE [type] = N'P' ORDER BY number;


--SELECT * FROM @Calendar

SELECT ISNULL(T.[Events],0) AS [Events],
       ISNULL(T.YearPart,C.TheYear) AS YearPart,
       ISNULL(T.MonthPart,C.TheMonth) AS MonthPart,
       ISNULL(T.YearName,DATENAME(YYYY,C.TheDate)) AS YearName,
       ISNULL(T.MonthName,DATENAME(MM,C.TheDate)) AS MonthName
FROM @Calendar C
LEFT JOIN 
(     
SELECT COUNT(*) AS Events,
       datepart(YYYY, call_date) AS YearPart,
       datepart(MM, call_date) As MonthPart,
       datename(YYYY, call_date) AS YearName,
       dateName(MM, call_date) As MonthName
FROM @rm_report 
GROUP BY 
    datename(year, call_date), 
    datename(month, call_date),
    datepart(year, call_date), 
    datepart(month, call_date)
    ) T 
     ON C.TheMonth=T.MonthPart AND C.TheYear = T.YearPart
ORDER BY 
    YearPart, 
    MonthPart;

答案 3 :(得分:0)

可以通过简单的选择

完成
DECLARE @rm_report table
(
    call_date datetime
)

INSERT @rm_report VALUES (GETDATE())

SELECT 
    (
        SELECT COUNT(*) 
        FROM @rm_report 
        WHERE YEAR(call_date) = year.Value AND MONTH(call_date) = month.Value
    ) AS Events,
    year.Value AS YearPart,
    month.Value AS MonthPart,
    year.Value AS YearName,
    DATENAME(MM, DATEADD(MONTH, month.Value, '2000-12-01')) AS MonthName
FROM 
    (VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12)) month(Value)
    CROSS JOIN 
    (
        SELECT DISTINCT YEAR(call_date) Value FROM @rm_report
    ) year