If I select from a table group by the month, day, year, it only returns rows with records and leaves out combinations without any records, making it appear at a glance that every day or month has activity, you have to look at the date column actively for gaps. How can I get a row for every day/month/year, even when no data is present, in T-SQL?
问题:
回答1:
Create a calendar table and outer join on that table
回答2:
My developer got back to me with this code, underscores converted to dashes because StackOverflow was mangling underscores -- no numbers table required. Our example is complicated a bit by a join to another table, but maybe the code example will help someone someday.
declare @career-fair-id int
select @career-fair-id = 125
create table #data ([date] datetime null, [cumulative] int null)
declare @event-date datetime, @current-process-date datetime, @day-count int
select @event-date = (select careerfairdate from tbl-career-fair where careerfairid = @career-fair-id)
select @current-process-date = dateadd(day, -90, @event-date)
while @event-date <> @current-process-date
begin
select @current-process-date = dateadd(day, 1, @current-process-date)
select @day-count = (select count(*) from tbl-career-fair-junction where attendanceregister <= @current-process-date and careerfairid = @career-fair-id)
if @current-process-date <= getdate()
insert into #data ([date], [cumulative]) values(@current-process-date, @day-count)
end
select * from #data
drop table #data
回答3:
Look into using a numbers table. While it can be hackish, it's the best method I've come by to quickly query missing data, or show all dates, or anything where you want to examine values within a range, regardless of whether all values in that range are used.
回答4:
Building on what SQLMenace said, you can use a CROSS JOIN to quickly populate the table or efficiently create it in memory.
http://www.sitepoint.com/forums/showthread.php?t=562806
回答5:
The task calls for a complete set of dates to be left-joined onto your data, such as
DECLARE @StartInt int
DECLARE @Increment int
DECLARE @Iterations int
SET @StartInt = 0
SET @Increment = 1
SET @Iterations = 365
SELECT
tCompleteDateSet.[Date]
,AggregatedMeasure = SUM(ISNULL(t.Data, 0))
FROM
(
SELECT
[Date] = dateadd(dd,GeneratedInt, @StartDate)
FROM
[dbo].[tvfUtilGenerateIntegerList] (
@StartInt,
,@Increment,
,@Iterations
)
) tCompleteDateSet
LEFT JOIN tblData t
ON (t.[Date] = tCompleteDateSet.[Date])
GROUP BY
tCompleteDateSet.[Date]
where the table-valued function tvfUtilGenerateIntegerList is defined as
-- Example Inputs
-- DECLARE @StartInt int
-- DECLARE @Increment int
-- DECLARE @Iterations int
-- SET @StartInt = 56200
-- SET @Increment = 1
-- SET @Iterations = 400
-- DECLARE @tblResults TABLE
-- (
-- IterationId int identity(1,1),
-- GeneratedInt int
-- )
-- =============================================
-- Author: 6eorge Jetson
-- Create date: 11/22/3333
-- Description: Generates and returns the desired list of integers as a table
-- =============================================
CREATE FUNCTION [dbo].[tvfUtilGenerateIntegerList]
(
@StartInt int,
@Increment int,
@Iterations int
)
RETURNS
@tblResults TABLE
(
IterationId int identity(1,1),
GeneratedInt int
)
AS
BEGIN
DECLARE @counter int
SET @counter= 0
WHILE (@counter < @Iterations)
BEGIN
INSERT @tblResults(GeneratedInt) VALUES(@StartInt + @counter*@Increment)
SET @counter = @counter + 1
END
RETURN
END
--Debug
--SELECT * FROM @tblResults