sql missing rows when grouped by DAY, MONTH, YEAR

2020-02-12 12:03发布

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?

5条回答
够拽才男人
2楼-- · 2020-02-12 12:37

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楼-- · 2020-02-12 12:43

Create a calendar table and outer join on that table

查看更多
放荡不羁爱自由
4楼-- · 2020-02-12 12:43

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.

查看更多
地球回转人心会变
5楼-- · 2020-02-12 12:44

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

查看更多
迷人小祖宗
6楼-- · 2020-02-12 12:48

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

查看更多
登录 后发表回答