简体   繁体   中英

Dynamic SQL Procedure with Pivot displaying counts based on Date Range

表

I have a table which contains multiple user entries. I want to pull counts of user entries based on date range passed to a stored procedure.

start date: 11/9/2017 end date: 11/11/2017

However the response needs to be dynamic based on amount of days in the date range.

Here is a desired format: 格式照片

If you are using MySQL this will make what you want:

SELECT  UserID,
        UserName,
        SUM(Date = '2017-11-09') '2017-11-09',
        SUM(Date = '2017-11-10') '2017-11-10',
        SUM(Date = '2017-11-11') '2017-11-11'
FROM src
GROUP BY UserID

If you are using SQL Server, you could try it with PIVOT:

SELECT *
FROM
(SELECT userID, userName, EntryDateTime
 FROM t) src
PIVOT
(COUNT(userID)
 FOR EntryDateTime IN (['2017-11-09'], ['2017-11-10'], ['2017-11-11'])) pvt

Now that you have provided examples, I have updated my answer which provides you with a solution based on the data you have provided.

Note that you are able to change the date range and the query will update accordingly.

Bare in mind that this SQL query is for SQL Server:

create table #tbl1 (
    [UserId] int
    ,[UserName] nvarchar(max)
    ,[EntryDateTime] datetime
);

insert into #tbl1 ([UserId],[UserName],[EntryDateTime])
values
    (1,'John Doe','20171109')
    ,(1,'John Doe','20171109')
    ,(1,'John Doe','20171110')
    ,(1,'John Doe','20171111')
    ,(2,'Mike Smith','20171109')
    ,(2,'Mike Smith','20171110')
    ,(2,'Mike Smith','20171110')
    ,(2,'Mike Smith','20171110')
;

-- declare variables
declare
    @p1 date
    ,@p2 date
    ,@diff int
    ,@counter1 int
    ,@counter2 int
    ,@dynamicSQL nvarchar(max)
;

-- set variables
set @p1 = '20171109';   -- ENTER THE START DATE IN THE FORMAT YYYYMMDD
set @p2 = '20171111';   -- ENTER THE END DATE IN THE FORMAT YYYYMMDD
set @diff = datediff(dd,@p1,@p2); -- used to calculate the difference in days
set @counter1 = 0;  -- first counter to be used in while loop
set @counter2 = 0;  -- second counter to be used in while loop
set @dynamicSQL = 'select pivotTable.[UserId] ,pivotTable.[UserName] as [Name] '; -- start of the dynamic SQL statement

-- to get the dates into the query in a dynamic way, you need to do a while loop (or use a cursor)
while (@counter1 < @diff)
begin
    set @dynamicSQL += ',pivotTable.[' + convert(nvarchar(10),dateadd(dd,@counter1,@p1),120) + '] '

    set @counter1 = (@counter1 +1)
end

-- continuation of the dynamic SQL statement
set @dynamicSQL += ' from (
    select
        t.[UserId]
        ,t.[UserName]
        ,cast(t.[EntryDateTime] as date) as [EntryDate]
        ,count(t.[UserId]) as [UserCount]
    from #tbl1 as t
    where
        t.[EntryDateTime] >= ''' + convert(nvarchar(10),@p1,120) + ''' ' +
        ' and t.[EntryDateTime] <= ''' + convert(nvarchar(10),@p2,120) + ''' ' +
    'group by
        t.[UserId]
        ,t.[UserName]
        ,t.[EntryDateTime]
    ) as mainQuery

    pivot (
        sum(mainQuery.[UserCount]) for mainQuery.[EntryDate]
            in ('
;

-- the second while loop which is used to create the columns in the pivot table
while (@counter2 < @diff)
begin
    set @dynamicSQL += ',[' + convert(nvarchar(10),dateadd(dd,@counter2,@p1),120) + ']'

    set @counter2 = (@counter2 +1)
end

-- continuation of the SQL statement
set @dynamicSQL += ')
    ) as pivotTable'
;

-- this is the easiet way I could think of to get rid of the leading comma in the query
set @dynamicSQL = replace(@dynamicSQL,'in (,','in (');

print @dynamicSQL   -- included this so that you can see the SQL statement that is generated

exec sp_executesql @dynamicSQL; -- this will run the generate dynamic SQL statement

drop table #tbl1;

Let me know if that's what you were looking for.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM