Как получить результат от динамической группировки - PullRequest
0 голосов
/ 14 мая 2019

На основе двух входных данных - дата (любая дата из календаря) и период даты (например, год, месяц или неделя), результат должен агрегировать данные:

На основе входных данных должны быть агрегированы данные в результатах @calenderDate и @period, например; если @period задан как ГОД, то он должен агрегировать результаты, основанные только на одном году,

когда @period задано как МЕСЯЦ, тогда оно должно агрегировать результаты на основе этого года и всех месяцев данного года,

когда @period задан как WEEK, тогда он должен агрегировать результаты на основе этого года и конкретного месяца и всех дней (между первым и последним днем ​​данной недели) в этой конкретной неделе

Я использовал динамическое группирование с помощью оператора CASE и сумел получить желаемый результат для @period = YEAR, но не для двух других входных данных, т.е. @period = MONTH и WEEK

Вот пример DDL;

CREATE TABLE [dbo].[transferTable](
    [ID] [bigint] IDENTITY(1000,1) NOT NULL,
    [transferDateTime] [datetime] NOT NULL,
    [transferAmount] [money] NOT NULL
) ON [PRIMARY]

GO
SET IDENTITY_INSERT [dbo].[transferTable] ON 

GO
INSERT [dbo].[transferTable] ([ID], [transferDateTime], [transferAmount]) VALUES (1000, CAST(0x0000AA2C0110897B AS DateTime), 10.0000)
GO
INSERT [dbo].[transferTable] ([ID], [transferDateTime], [transferAmount]) VALUES (1001, CAST(0x0000AA2D00F0AA50 AS DateTime), 151.0000)
GO
INSERT [dbo].[transferTable] ([ID], [transferDateTime], [transferAmount]) VALUES (1002, CAST(0x0000A8850110897B AS DateTime), 10.0000)
GO
INSERT [dbo].[transferTable] ([ID], [transferDateTime], [transferAmount]) VALUES (1003, CAST(0x0000AA0E0121043B AS DateTime), 151.0000)
GO
SET IDENTITY_INSERT [dbo].[transferTable] OFF
GO

вот мой код:


DECLARE @calenderDate DATETIME2(0) = '2019-04-12'
DECLARE @period varchar(20) = 'MONTH'

DECLARE @year varchar(10) =  DATEPART(YEAR,@calenderDate) 
DECLARE @month varchar(10) =  DATEPART(MONTH,@calenderDate)
DECLARE @week varchar(10) =  DATEPART(WEEK,@calenderDate) 

select case when @period = 'YEAR' then DATEPART(YEAR,transferDateTime)
            when @period = 'MONTH' then DATEPART(MONTH,transferDateTime)
            when @period = 'WEEK' then DATEPART(WEEKDAY,transferDateTime)
 end as period, 
     COUNT (t.transferAmount) as volOfTxns,
     SUM (t.transferAmount) as ValueOfTxns
from transferTable t
where 
     ( 
      (DATEPART(YEAR,t.transferDateTime) = @year) OR 
      (DATEPART(YEAR,t.transferDateTime) = @year AND DATEPART(MONTH,t.transferDateTime) = @month)
      )

group by case when @period = 'YEAR' then DATEPART(YEAR,transferDateTime)
              when @period = 'MONTH' then DATEPART(MONTH,transferDateTime)
              when @period = 'WEEK' then DATEPART(WEEKDAY,transferDateTime)
          end

Когда @calenderDate = ‘2019-04-12 ’и @period =‘ YEAR ’, тогда должно отображаться,

period  volOfTxns   ValueOfTxns
2019    3   302.00

Когда @calenderDate = ‘2019-04-12’ и @period = ‘MONTH, тогда должно отображаться,

period  volOfTxns   ValueOfTxns
4   2   161.00

Аналогично, когда @calenderDate = ‘2019-03-12’ и @period = ‘MONTH, тогда должно отображаться,

period  volOfTxns   ValueOfTxns
3   1   151.00

Когда @calenderDate = ‘2019-04-12’ и @period = ‘WEEK, тогда должно отображаться,

period  volOfTxns   ValueOfTxns
11           1             10
12           1             151

Ответы [ 2 ]

1 голос
/ 14 мая 2019

В случае изменения условия where можно включить только те строки, которые соответствуют периоду, в который вы просматриваете.Ваш предыдущий код корректно фильтровал только тот год, в который вы смотрели.

DECLARE @calenderDate DATETIME2(0) = '2019-04-12'
DECLARE @period varchar(20) = 'MONTH'

DECLARE @year varchar(10) =  DATEPART(YEAR,@calenderDate) 
DECLARE @month varchar(10) =  DATEPART(MONTH,@calenderDate)
DECLARE @week varchar(10) =  DATEPART(WEEK,@calenderDate) 

select case when @period = 'YEAR' then DATEPART(YEAR,transferDateTime)
            when @period = 'MONTH' then DATEPART(MONTH,transferDateTime)
            when @period = 'WEEK' then DATEPART(WEEKDAY,transferDateTime)
 end as period, 
     COUNT (t.transferAmount) as volOfTxns,
     SUM (t.transferAmount) as ValueOfTxns
from transferTable t
where 

      CASE 
            WHEN @period = 'WEEK' THEN 
                CASE 
                    WHEN DATEPART(YEAR, t.transferDateTime) = @year 
                        AND DATEPART(MONTH, t.TransferDateTime) = @month
                        AND DATEPART(WEEK, t.transferDateTime) = @week
                    THEN 1
                    ELSE 0 
                END
            WHEN @period = 'MONTH' THEN
                CASE 
                    WHEN DATEPART(YEAR, t.transferDateTime) = @year 
                        AND DATEPART(MONTH, t.TransferDateTime) = @month
                    THEN 1
                    ELSE 0 
                END
            WHEN @period = 'YEAR' THEN
                CASE 
                    WHEN DATEPART(YEAR, t.transferDateTime) = @year 
                    THEN 1
                    ELSE 0 
                END
            ELSE 0
        END = 1

group by case when @period = 'YEAR' then DATEPART(YEAR,transferDateTime)
              when @period = 'MONTH' then DATEPART(MONTH,transferDateTime)
              when @period = 'WEEK' then DATEPART(WEEKDAY,transferDateTime)
          end

Выше приведен пример, и есть много более коротких способов сделать это, однако я сделал это, как указано выше.чтобы показать логику немного лучше.

1 голос
/ 14 мая 2019

измените ваше предложение WHERE на ниже

where   (
        (@period = 'YEAR'   AND DATEPART(YEAR,t.transferDateTime) = @year)
    OR  (@period = 'MONTH'  AND DATEPART(MONTH,t.transferDateTime) = @month)
    OR  (@period = 'WEEK'   AND DATEPART(WEEK,t.transferDateTime) = @week)
    )

На WEEK я не уверен, что вы хотели WEEK или WEEKDAY, так как вы ссылаетесь на оба в своем запросе.И не уверен, почему в ожидаемом результате есть 2 строки для WEEK

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...