简体   繁体   English

如何从动态分组中获得结果

[英]How to get result from dynamic grouping

Based on two inputs - date (any date from calendar) and period of date (like Year,month or week) result should aggregate data: 基于两个输入-日期(日历中的任何日期)和日期期限(例如,年,月或周),结果应汇总数据:

Based on the inputs the data in @calenderDate and @period result should be aggregated, for example; 例如,应基于输入将@calenderDate和@period结果中的数据进行汇总; when @period is given as YEAR then it should aggregate results based on the year alone, 当@period表示为YEAR时,则应仅基于年份汇总结果,

when @period is given as MONTH then it should aggregate results based on that year and all the month in given year, 当@period设为MONTH时,则应基于该年以及该年的所有月份汇总结果,

when @period is given as WEEK then it should aggregate results based on that year and the specific month and all the days (between first day and last day of the given week) in that specific week 当@period设为WEEK时,则应基于该年和特定月份以及该特定周中的所有天(在给定周的第一天和最后一天之间)汇总结果

I have used dynamic grouping using CASE statement and managed to get desired result for the @period = YEAR, but not for other two inputs ie @period = MONTH and WEEK 我已经使用CASE语句进行了动态分组,并设法为@period = YEAR获得了期望的结果,但没有为其他两个输入(即@period = MONTH和WEEK)获得期望的结果

Here is the sample DDL; 这是示例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

here is my code : 这是我的代码:


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

When @calenderDate = '2019-04-12' and @period = 'YEAR' then it should show, 当@calenderDate ='2019-04-12'和@ period ='YEAR'时,它应该显示,

period  volOfTxns   ValueOfTxns
2019    3   302.00

When @calenderDate = '2019-04-12' and @period = 'MONTH then it should show, 如果@calenderDate ='2019-04-12'和@ period ='MONTH,则应显示,

period  volOfTxns   ValueOfTxns
4   2   161.00

Likewise when @calenderDate = '2019-03-12' and @period = 'MONTH then it should show, 同样,当@calenderDate ='2019-03-12'和@ period ='MONTH时,它应该显示,

period  volOfTxns   ValueOfTxns
3   1   151.00

When @calenderDate = '2019-04-12' and @period = 'WEEK then it should show, 当@calenderDate ='2019-04-12'和@ period ='WEEK时,它将显示,

period  volOfTxns   ValueOfTxns
11           1             10
12           1             151

change your WHERE clause to below 将您的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)
    )

On the WEEK , I am not sure you wanted WEEK or WEEKDAY , as you reference both in your query. WEEK ,我不确定您要使用WEEK还是WEEKDAY ,因为您在查询中都引用了这两者。 And not sure why there are 2 rows in your expected result for WEEK 并且不确定为什么您的WEEK预期结果中有2行

It would be a case of modifying your where clause to only include the rows that match the period in which you are looking at. 可能需要修改where子句,使其仅包含与您要查看的时间段匹配的行。 Your previous code was only filtering correctly to the year in which you were looking at. 您以前的代码仅正确过滤到您所看的年份。

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

The above is an example and there are many shorter ways of doing this, however I've done it like the above to show the logic a bit better. 上面是一个示例,并且有许多更短的方法可以执行此操作,但是我已经像上面那样完成了操作,以更好地说明逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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