Динамический сводный запрос SQL Server

Я создаю динамический сводный запрос, который показывает общее количество NetAmount за неделю для каждого клиента в указанном диапазоне дат. Проблема в том, что он НЕ ДОБАВЛЯЕТ ВСЕ NetAmount в течение недели. Вот данные tblSampleSalesInvoices:

введите описание изображения здесь

Вот мой сценарий.

CREATE PROCEDURE uspSalesWeeklySummary 
(
    @CustomerId INT,
    @FromDate DATETIME,
    @ToDate DATETIME
)
AS 

SET NOCOUNT ON

DECLARE @Query AS VARCHAR(MAX)
DECLARE @DateStart DATETIME = @FromDate 
DECLARE @tmp TABLE ([Date] VARCHAR(MAX))
DECLARE @Month VARCHAR(MAX)
DECLARE @Day VARCHAR(MAX)
DECLARE @ColumnHeader VARCHAR(MAX)
DECLARE @Headers VARCHAR(MAX)

WHILE DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @DateStart), '19050101') <= DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @ToDate), '19050101')
BEGIN

    SET @month = DATENAME(Month, DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @DateStart), '19050101'))
    SET @day = CAST( DATEPART(DD, DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @DateStart), '19050101')) AS VARCHAR(MAX) ) 

    SET @ColumnHeader = 'Week ' + CAST(DatePart(WEEK,@DateStart) AS VARCHAR(MAX)) + ' - ' + CAST(Year(DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @DateStart), '19050101')) AS VARCHAR(MAX)) + ' - ' + @month + ' - ' + @day

    INSERT INTO @tmp ([Date])
    VALUES (@ColumnHeader)

    SET @DateStart = DATEADD(DD, 7, @DateStart)

END


SELECT @Headers = ISNULL(@Headers + ',','') + QUOTENAME(t.[Date])
FROM @tmp t

SET @Headers = @Headers + ',[Grand Total]'

    SET @Query =
    '
    DECLARE @CustomerId INT = ' + CAST(@CustomerId AS VARCHAR) + '
    DECLARE @FromDate DATETIME = CAST(''' + CAST(@FromDate AS VARCHAR) + ''' AS DATETIME)
    DECLARE @ToDate DATETIME = CAST(''' + CAST(@ToDate AS VARCHAR) + ''' AS DATETIME)
    DECLARE @Headers VARCHAR(MAX) = ''' + CAST(@Headers AS VARCHAR(MAX)) + '''

    SELECT *
    FROM
    (   
    SELECT c.CustomerName AS CustomerName, 
            ''Week '' + CAST(DatePart(WEEK,si.TransactionDate) AS VARCHAR(MAX)) + '' - '' 
            + CAST(Year(DATEADD(WEEK, DATEDIFF(WEEK, ''19050101'', si.TransactionDate), ''19050101'')) AS VARCHAR(MAX)) + '' - '' 
            + CAST(DATENAME(Month, DATEADD(WEEK, DATEDIFF(WEEK, ''19050101'', si.TransactionDate), ''19050101'')) AS VARCHAR(MAX)) + '' - '' 
            + CAST(DATEPART(DD, DATEADD(WEEK, DATEDIFF(WEEK, ''19050101'', si.TransactionDate), ''19050101'')) AS VARCHAR(MAX)) AS Header,
            SUM(si.NetAmount) AS NetAmount
    FROM tblSampleSalesInvoices si
        LEFT OUTER JOIN tblSampleCustomers c ON c.Id = si.CustomerId
    WHERE (si.TransactionDate BETWEEN @FromDate AND DATEADD(WEEK, DATEDIFF(WEEK, ''19050101'', DATEADD(DD, 7 , @ToDate)), ''19050101''))
        AND (si.CustomerId = @CustomerId OR @CustomerId = 0)
    GROUP BY c.CustomerName, si.TransactionDate

    UNION ALL

    SELECT c.CustomerName AS CustomerName, 
            ''Grand Total'' AS Header,
            SUM(si.NetAmount) AS NetAmount
    FROM tblSampleSalesInvoices si
        LEFT OUTER JOIN tblSampleCustomers c ON c.Id = si.CustomerId
    WHERE (si.TransactionDate BETWEEN @FromDate AND DATEADD(WEEK, DATEDIFF(WEEK, ''19050101'', DATEADD(DD, 7 , @ToDate)), ''19050101''))
        AND (si.CustomerId = @CustomerId OR @CustomerId = 0)
    GROUP BY c.CustomerName

    ) AS BaseData
    PIVOT
    (   
        SUM(NetAmount)
        FOR Header IN (' + @Headers + ') 
    ) AS Pivoting'


EXEC (@Query)


GO

EXEC uspSalesWeeklySummary 0,'01/01/2016','02/01/2016'

В этом сценарии сумма NetAmount будет равна 10000 только потому, что со дня 1 января 2016 года по 1 февраля 2016 года была сделана только 1 транзакция (TR0002). Но когда я помещаю в параметры параметры 27 декабря 2015 года и 1 февраля 2016 года. Он показывает только NetAmount TR0001 вместо 25000, который является суммой TR0001 и TR0002.

введите описание изображения здесь

1 ответ

Если вы ищете номера недель относительно даты начала и можете создать # таблицы, тогда это может подойти

CREATE PROCEDURE uspSalesWeeklySummary 
(
    @CustomerId INT,
    @FromDate DATETIME,
    @ToDate DATETIME
)
AS 
SET NOCOUNT ON
set datefirst 1
/*
create table tblSampleSalesInvoices (id int,transactionNo int,customerid int,TransactionDate date,netamount int)
insert into  tblSampleSalesInvoices values
(1,1,1,'2015-12-29',15000),
(2,2,1,'2016-01-01',15000),
(3,3,2,'2016-03-01',15000),
(4,4,3,'2016-04-01',15000),
(5,5,4,'2016-06-01',15000),
(6,6,1,'2016-09-01',15000),
(7,7,2,'2016-10-01',15000),
(8,8,3,'2016-12-01',15000),
(9,9,4,'2017-01-01',15000),
(10,10,1,'2017-04-01',15000),
(11,11,2,'2017-07-01',15000),
(12,12,3,'2017-10-01',15000),
(13,13,4,'2017-12-01',15000)
*/
--declare    @CustomerId INT    = 1
--declare    @FromDate DATETIME = '2015-12-27'
--declare    @ToDate DATETIME   = '2016-02-01'

DECLARE @Query AS VARCHAR(MAX)
DECLARE @DateStart DATETIME = @FromDate 

IF OBJECT_ID(N'tempdb..#Tempdates') IS NOT NULL
BEGIN
    DROP TABLE #Tempdates
END
declare @id         int = 0
create  table #tempdates (id int,[lodate] date, [hidate] date ,yyyy varchar(4), mm varchar(max), dd int,txt varchar(max))

DECLARE @Month VARCHAR(MAX)
DECLARE @Day VARCHAR(MAX)
DECLARE @ColumnHeader VARCHAR(MAX)
DECLARE @Headers VARCHAR(MAX)


WHILE DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @DateStart), '19050101') <= DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @ToDate), '19050101')
BEGIN
    set datefirst 1
    SET @month = DATENAME(Month, DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @DateStart), '19050101'))
    SET @day = CAST( DATEPART(DD, DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @DateStart), '19050101')) AS VARCHAR(MAX) ) 

    SET @ColumnHeader = 'Week ' + CAST(DatePart(WEEK,@DateStart) AS VARCHAR(MAX)) + ' - ' + 
            CAST(Year(DATEADD(WEEK, DATEDIFF(WEEK, '19050101', @DateStart), '19050101')) AS VARCHAR(MAX)) + ' - ' + @month + ' - ' + @day

    set @id = @id + 1

    insert into #tempdates (id,[lodate],[hidate],yyyy,mm,dd,txt)
    values (@id,@datestart,dateadd(dd,6,@datestart),
    year(@datestart),
    datename(month,@datestart),day(@datestart), 
    'Week ' + cast(@id as varchar(2)) + ' - ' + cast(datename(month,@datestart) as varchar(max)) + ' - ' + cast(day(@datestart) as varchar(max))
    )

    SET @DateStart = DATEADD(DD, 7, @DateStart)

END
update #tempdates 
    set hidate = @todate where id = @id

SELECT @Headers = ISNULL(@Headers + ',','') + QUOTENAME(t.[txt])
FROM #tempdates t

SET @Headers = @Headers + ',[Grand Total]'

--select @headers headers
--select * from #tempdates

set @query = 
'

 DECLARE @CustomerId INT = ' + CAST(@CustomerId AS VARCHAR) + '
    DECLARE @FromDate DATETIME = CAST(''' + CAST(@FromDate AS VARCHAR) + ''' AS DATETIME)
    DECLARE @ToDate DATETIME = CAST(''' + CAST(@ToDate AS VARCHAR) + ''' AS DATETIME)
    DECLARE @Headers VARCHAR(MAX) = ''' + CAST(@Headers AS VARCHAR(MAX)) + '''  
 SELECT *
    FROM
    (   
    SELECT  si.customerid, 
            t.txt as header,
            SUM(si.NetAmount) AS NetAmount
    FROM tblsamplesalesinvoices si
    left join   #tempdates  t on si.Transactiondate between lodate and hidate
    --LEFT OUTER JOIN tblSampleCustomers c ON c.Id = si.CustomerId
    WHERE si.TransactionDate BETWEEN @FromDate AND DATEADD(WEEK, DATEDIFF(WEEK, ''19050101'', DATEADD(DD, 7 , @ToDate)), ''19050101'')
        AND (si.CustomerId = @CustomerId OR @CustomerId = 0)
    GROUP BY -- c.CustomerName, 
            si.customerid
            ,
            t.txt

    UNION ALL

    SELECT si.CustomerId,
            ''Grand Total'' AS Header,
            SUM(si.NetAmount) AS NetAmount
    FROM tblsamplesalesinvoices si
    -- LEFT OUTER JOIN tblSampleCustomers c ON c.Id = si.CustomerId
    WHERE (si.TransactionDate BETWEEN @FromDate AND DATEADD(WEEK, DATEDIFF(WEEK, ''19050101'', DATEADD(DD, 7 , @ToDate)), ''19050101''))
       AND (si.CustomerId = @CustomerId OR @CustomerId = 0)
    GROUP BY si.customerid

) s

 PIVOT
    (   
        SUM(NetAmount)
        FOR Header IN (' + @Headers + ') 
    ) AS Pivoting'

--select @query
exec (@query)
IF OBJECT_ID(N'tempdb..#Tempdates') IS NOT NULL
BEGIN
    DROP TABLE #Tempdates
END

go

Обратите внимание, даты в Великобритании локализованы

Другие вопросы по тегам