通过SQL SERVER进行分区业务案例

时间:2015-06-12 09:31:08

标签: sql sql-server sql-server-2012 window-functions

我需要一些问题的帮助。我在SQL SERVER 2012中工作。基本上就是这种情况:

客户可以购买三种产品:

  1. A
  2. C
  3. 如果客户 购买两种产品 (任何组合,例如,A + B或B + C或CA,任何产生两种产品的组合) 当天 ,我们应将其显示为“ Dual ”。

    如果客户仅在 当天 购买1件产品,那么我们应将其称为“单件”。

    如果客户在当天购买所有产品,我们应将其称为“三次”。

    这就是我目前的数据:

       YearMonth   Product CustomerNr        Sales Date
        201505      B      70056844         20150501
        201505      A      70056844         20150501
        201505      B      70057297         20150503
        201505      A      70057494         20150504
        201505          B      70057494         20150504
        201505      C      70057494         20150504
        201505      B      70033055         20150506
        201505      B      36021632         20150508
        201505      A      70060612         20150508
        201505      C      70060612         20150508
    

    正如我们在样本数据中所见,客户编号:70060612已在同一销售日期购买了两种产品A和C,因此我们可以说他购买了双包装。客户编号:70057494已在同一销售日期购买了3种产品,A,B和C.我们称之为Triple。

    我希望我的数据包含这样的列:

       YearMonth   Product CustomerNr        Sales Date  Package        
        201505      B      70056844         20150501    Dual
        201505      A      70056844         20150501    Dual
        201505      B      70057297         20150503    Single
        201505      A      70057494         20150504    Triple
        201505          B      70057494         20150504    Triple
        201505      C      70057494         20150504    Triple
        201505      B      70033055         20150506    Single
        201505      B      36021632         20150508    Single
        201505      A      70060612         20150508    Dual
        201505      C      70060612         20150508    Dual
    

    我该怎么做?我想做一些像

     Test=COUNT(*) OVER (PARTITION BY CustomerNr)
    

2 个答案:

答案 0 :(得分:1)

这是一个带有相应数据示例的解决方案。希望这会对你有所帮助。

create table #t(dt datetime, prod char(1), customer int)
declare @date datetime = getdate()

insert into #t(dt,prod,customer)
values(@date,N'A',1),(@date,N'A',1),(@date,N'C',1),(@date,N'B',2),(@date,N'C',2),(@date,N'B',3),(@date,N'A',3),(@date,N'A',4),(@date,N'B',5),(@date,N'C',6),
(@date,N'A',7),(@date,N'B',7),(@date,N'C',7)


SELECT dt,prod,customer, MAX(cntDay) OVER(PARTITION BY customer, dt) as cntDay, 
    CASE MAX(cntDay) OVER(PARTITION BY customer, dt)
        WHEN 2 THEN N'Dual'
        WHEN 3 THEN N'Triple'
        ELSE N'Single' END as package -- Your Case
FROM (
    SELECT *, DENSE_RANK() OVER(PARTITION BY customer, dt ORDER BY prod) as cntDay
    FROM #t
) as dat
ORDER BY customer, dt -- just for a better overview

drop table #t

最好的问候,离子

答案 1 :(得分:1)

不幸的是,SQL不允许COUNT(Distinct) OVERDENSE_RANK()是一种解决方法

DECLARE @Table table
(
    id int identity(1,1) primary key,
    YearMonth int,
    Product char(1),
    CustomerNr int,
    SalesDate date
)

INSERT @Table VALUES
(201505, 'B', 70056844, '20150501'),
(201505, 'A', 70056844, '20150501'),
(201505, 'B', 70057297, '20150503'),
(201505, 'A', 70057494, '20150504'),
(201505, 'B', 70057494, '20150504'),
(201505, 'C', 70057494, '20150504'),
(201505, 'B', 70033055, '20150506'),
(201505, 'B', 36021632, '20150508'),
(201505, 'A', 70060612, '20150508'),
(201505, 'C', 70060612, '20150508'),
(201505, 'A', 70056844, '20150501') -- Additional for duplicated product

SELECT 
    *, 
    CASE 
        DENSE_RANK() OVER (PARTITION BY CustomerNr, SalesDate ORDER BY Product)
         + DENSE_RANK() OVER (PARTITION BY CustomerNr, SalesDate ORDER BY Product DESC) - 1
        WHEN 1 THEN 'Single'
        WHEN 2 THEN 'Dual'
        WHEN 3 THEN 'Triple'
        ELSE 'Multiple' -- Not defined case 
    END AS Package
FROM 
    @Table
ORDER BY 
    id

<强>结果

id          YearMonth   Product CustomerNr  SalesDate  Package
----------- ----------- ------- ----------- ---------- --------
1           201505      B       70056844    2015-05-01 Dual
2           201505      A       70056844    2015-05-01 Dual
3           201505      B       70057297    2015-05-03 Single
4           201505      A       70057494    2015-05-04 Triple
5           201505      B       70057494    2015-05-04 Triple
6           201505      C       70057494    2015-05-04 Triple
7           201505      B       70033055    2015-05-06 Single
8           201505      B       36021632    2015-05-08 Single
9           201505      A       70060612    2015-05-08 Dual
10          201505      C       70060612    2015-05-08 Dual
11          201505      A       70056844    2015-05-01 Dual