繁体   English   中英

如何在SQL Server中的特定日期范围内或每隔几天对值进行分组

[英]How to group value within a certain date range or every certain days in SQL server

例如表将是:

Customer   OrderDate   OrderAmt
--------   ----------  ---------
A1          20140101      920.00
A2          20140111      301.00
A2          20140123      530.00
A1          20140109      800.00
A3          20140110      500.00
A1          20140115      783.00
A3          20140217      500.00
A1          20140219     1650.00
A1          20140225      780.00
...
A3          20140901      637.00

我想将它们分组并计算每20天的总和(OrderAmt),然后从20140101开始按客户分组。

假设OrderDate是一个数字字段(不是varchar)。 我还假设您将来不需要走超过一年。 如果要显示间隙,则保持左连接,如果不希望间隙,则使其成为内部联接。 (您还可以将硬编码日期作为开始位置的变量,我只是将其保留为您提到的20140101。

with Numbers as 
(Select 0 as Num 
    UNION ALL 
 Select Num+1 
 FROM Numbers 
 WHERE Num+1<= 20
)
, DateList AS
(Select  Year(DateAdd(dd,20*(Num), Cast('2014-01-01' as date))) * 10000+Month(DateAdd(dd,20*(Num), Cast('2014-01-01' as date)))*100+Day(DateAdd(dd,20*(Num), Cast('2014-01-01' as date))) Groupingdatemin
, Year(DateAdd(dd,20*(Num+1)-1, Cast('2014-01-01' as date)))*10000+ MONTH(DateAdd(dd,20*(Num+1)-1, Cast('2014-01-01' as date)))*100+DAY(DateAdd(dd,20*(Num+1)-1, Cast('2014-01-01' as date))) Groupingdatemax
from Numbers
) 
select Customer, sum(orderamt), Groupingdatemin, Groupingdatemax from DateLIst d LEFT JOIN 
    <yourtable> t on t.orderdate between d.Groupingdatemin and d.Groupingdatemax
group by customer, Groupingdatemin, Groupingdatemax

对于它的价值,您可以使用一个非常简单的DATEDIFF() / GROUP BY操作完成您描述的内容,如下所示:这是否实际上是您想要的,可能是另一个问题。 我怀疑DateBucket计算实际上可能是其他东西...

CREATE TABLE #tmpCustomer (Customer VARCHAR(2), OrderDate VARCHAR(10), OrderAmt DECIMAL(6,2))

INSERT INTO #tmpCustomer (Customer, OrderDate, OrderAmt)


SELECT 'A1',20140101,      920.00 UNION
SELECT 'A2',20140111,      301.00 UNION
SELECT 'A2',20140123,      530.00 UNION
SELECT 'A1',20140109,      800.00 UNION
SELECT 'A3',20140110,      500.00 UNION
SELECT 'A1',20140115,      783.00 UNION
SELECT 'A3',20140217,      500.00 UNION
SELECT 'A1',20140219,     1650.00 UNION
SELECT 'A1',20140225,      780.00 UNION
SELECT 'A3',20140901,      637.00


SELECT 
    Customer, 
    (DATEDIFF(day, '1/1/2014', CAST(OrderDate AS DATE)) / 20) + 1 AS DateBucket, 
    SUM(OrderAmt) SumOrderAmt
FROM #tmpCustomer
GROUP BY Customer, (DATEDIFF(day, '1/1/2014', CAST(OrderDate AS DATE)) / 20) + 1
ORDER BY Customer, DateBucket 

您需要做两件事:(1)创建某种包含“ 20天小组”信息的指南。 递归CTE可以很好地做到这一点,并且(2)将varchar日期重铸为实际日期以进行比较。

然后,它只是将订单数据加入该日期范围分组,并对订单金额求和。

-------------------------
-- Here i'm just recreating your example
-------------------------
DECLARE @customerOrder TABLE (Customer varchar(2), OrderDate varchar(8), OrderAmt decimal(8,2))
INSERT INTO @customerOrder (Customer, OrderDate, OrderAmt)
VALUES
    ('A1', '20140101', 920.00),
    ('A2', '20140111', 301.00),
    ('A2', '20140123', 530.00),
    ('A1', '20140109', 800.00),
    ('A3', '20140110', 500.00),
    ('A1', '20140115', 783.00),
    ('A3', '20140217', 500.00),
    ('A1', '20140219', 1650.00),
    ('A1', '20140225', 780.00),
    ('A3', '20140901', 637.00)

-------------------------
-- Set up a table that lists off 20 day periods starting from 1/1/2014
-------------------------
DECLARE @startDate datetime, @endDate datetime; 

SET @startDate = {d N'2014-01-01'}; 
SET @endDate   = {d N'2014-12-31'}; 

WITH [dates] ([Sequence], [startDate], [maxExcludedDate]) AS 
   (SELECT 1 AS [Sequence] 
          ,@startDate AS [startDate] 
          ,DATEADD(d, 20, @startDate) AS [maxExcludedDate] 

    UNION ALL 
    SELECT Sequence + 1 AS Sequence 
          ,DATEADD(d, 20, [startDate]) AS [startDate] 
          ,DATEADD(d, 40, [startDate]) AS [maxExcludedDate]
    FROM [dates] 
    WHERE [startDate] < @endDate
) 
, dateFrame AS
( 
    SELECT 
          [startDate] 
          ,[maxExcludedDate]

    FROM [dates] 
)
-------------------------
-- Set up a table that holds the orderDates as actual dates
-------------------------
, castData AS
(
    SELECT
        cast(orderdate as datetime) castDate
        ,OrderAmt
    FROM @customerOrder
)

-------------------------
-- JOIN and sum.
-------------------------
SELECT
    [startDate]
    , Sum(OrderAmt) perodAmt
FROM
    dateFrame df

    left join castData cd
        on cd.castDate >= df.startDate
        and cd.castDate < df.maxExcludedDate
GROUP BY
    [startDate]

ORDER by
    [startDate]

暂无
暂无

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

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