我为报告编写了一个选择查询,该查询可以获取一年中数月的计数。结果表看起来像..
rep_name month year count
----------------------------------
repo1 1 2013 5
repo1 4 2013 6
repo1 12 2013 18
repo1 2 2014 20
.
.
等等。在我的案例中,所需的输出是一个表格,显示所有月份的记录。即使没有可用的数据,也需要显示计数为0的记录,如
rep_name month year count
----------------------------------
repo1 1 2013 5
repo1 2 2013 0
repo1 3 2013 0
repo1 4 2013 6
repo1 5 2013 0
repo1 6 2013 0
repo1 7 2013 0
repo1 8 2013 0
repo1 9 2013 0
repo1 10 2013 0
repo1 11 2013 0
repo1 12 2013 18
.
.
.
之前有过类似的查询,但数据集限制为3。 select statement to always return 3 rows on execution
在这种情况下,我无法确定会显示多少个月。这取决于可用的数据。
答案 0 :(得分:4)
好吧你想要做的就是自己Calendar Table这些非常有用,每个数据库都应该有一个。关于该链接断开的可能性是包含的脚本。
/** Create Date Dimension Table **/
/* Create First numbers table for key generation */
CREATE TABLE Numbers_Small (Number INT);
INSERT INTO Numbers_Small
VALUES (0)
,(1)
,(2)
,(3)
,(4)
,(5)
,(6)
,(7)
,(8)
,(9);
GO
/* Create Second numbers table for key generation */
CREATE TABLE Numbers_Big (Number_Big BIGINT);
INSERT INTO Numbers_Big (Number_Big)
SELECT (tenthousands.number * 10000 + thousands.number * 1000 + hundreds.number * 100 + tens.number * 10 + ones.number) AS number_big
FROM numbers_small tenthousands
,numbers_small thousands
,numbers_small hundreds
,numbers_small tens
,numbers_small ones;
GO
/* Create Date Dimension Table */
CREATE TABLE [dbo].[DimDate] (
[DateKey] [int] NOT NULL
,[Date] [datetime] NOT NULL
,[Day] [char](10) NULL
,[DayOfWeek] [smallint] NULL
,[DayOfMonth] [smallint] NULL
,[DayOfYear] [smallint] NULL
,[PreviousDay] [datetime] NULL
,[NextDay] [datetime] NULL
,[WeekOfYear] [smallint] NULL
,[Month] [char](10) NULL
,[MonthOfYear] [smallint] NULL
,[QuarterOfYear] [smallint] NULL
,[Year] [int] NULL
);
GO
/* Create Date Key and Date Fields */
INSERT INTO [DimDate] (
DateKey
,DATE
)
SELECT number_big
,DATEADD(day, number_big, '1900-01-01') AS DATE
FROM numbers_big
WHERE DATEADD(day, number_big, '1900-01-01') BETWEEN '1900-01-01'
AND '2030-12-31'
ORDER BY number_big;
GO
/* Update all other fields with appropriate data. */
UPDATE [DimDate]
SET Day = DATENAME(DW, DATE)
,DayOfWeek = DATEPART(WEEKDAY, DATE)
,DayOfMonth = DAY(DATE)
,DayOfYear = DATEPART(DY, DATE)
,PreviousDay = DATEADD(DAY, - 1, DATE)
,NextDay = DATEADD(DAY, 1, DATE)
,WeekOfYear = DATEPART(WK, DATE)
,Month = DATENAME(MONTH, DATE)
,MonthOfYear = MONTH(DATE)
,QuarterOfYear = DATEPART(Q, DATE)
,Year = YEAR(DATE);
GO
/* Drop Temp Tables */
DROP TABLE Numbers_Small;
DROP TABLE Numbers_Big;
所以,现在添加了该表后,只需在月份上为您的DimDate表格执行LEFT JOIN
,然后就可以了。
答案 1 :(得分:1)
此代码从源表中动态提取 min 和 max 日期,然后递归生成日期介于 min 和 max之间的表格日期,最后使用生成的日期加入源表。没有更新,插入,DDL等 - 一个CTE:)
/*
-- generating fake #your_table
select * into #your_table
from (values
('repo1', 1, 2013, 5),
('repo1', 4, 2013, 6),
('repo1', 12, 2013, 18),
('repo1', 2, 2014, 20)) as your_table(rep_name, [month], [year], [count]);
*/
with min_max_days as (
select min(dateadd(day, -1, dateadd(year, [year]-1900, dateadd(month, [month], '1900-01-01')))) [min_day]
, max(dateadd(day, -1, dateadd(year, [year]-1900, dateadd(month, [month], '1900-01-01')))) [max_day] from #your_table),
[base] as (
select (select year([min_day]) from min_max_days) [year], (select month([min_day]) from min_max_days) [month], (select [min_day] from min_max_days) [date]
union all
select year(dateadd(month, 1, [date])) [year], month(dateadd(month, 1, [date])) [month], dateadd(month, 1, [date])
from [base]
where [date] < (select [max_day] from min_max_days))
select isnull(t.rep_name, 'repo1') [rep_name]
, b.[month]
, b.[year]
, isnull(t.[count], 0) [count]
from [base] b
left join #your_table t on b.[year] = t.[year]
and b.[month] = t.[month];
rep_name month year count
--------------------------------
repo1 1 2013 5
repo1 2 2013 0
repo1 3 2013 0
repo1 4 2013 6
repo1 5 2013 0
repo1 6 2013 0
repo1 7 2013 0
repo1 8 2013 0
repo1 9 2013 0
repo1 10 2013 0
repo1 11 2013 0
repo1 12 2013 18
repo1 1 2014 0
repo1 2 2014 20
请查看SQL Fiddle