连续4次购买更新列

时间:2017-06-13 07:47:52

标签: sql-server database tsql

我需要将整个用户的结果列值更新为,如果用户确实连续4次购买而没有获得奖励之间。如何才能做到这一点。请参阅下面的代码.....

 -- drop table #Test
 CREATE TABLE #Test (UserID int, TheType VARCHAR(10), TheDate DATETIME, Result VARCHAR(10))
 INSERT INTO #Test
 SELECT 1234, 'Bonus', GETDATE(), NULL
 UNION
 SELECT 1234, 'Purchase', GETDATE()-1, NULL
 UNION
 SELECT 1234, 'Purchase', GETDATE()-2, NULL
  UNION
 SELECT 1234, 'Purchase', GETDATE()-3, NULL
  UNION
 SELECT 1234, 'Purchase', GETDATE()-4, NULL
  UNION
 SELECT 1234, 'Bonus', GETDATE()-5, NULL
  UNION
 SELECT 1234, 'Purchase', GETDATE()-6, NULL
  UNION
 SELECT 1234, 'Bonus', GETDATE()-7, NULL

 SELECT * FROM #Test ORDER BY TheDate

再次请注意,购买需要连续(By TheDate)

2 个答案:

答案 0 :(得分:2)

您可以如下所示:

;WITH CTE1
 AS
 (
     SELECT 
        ROW_NUMBER() OVER (ORDER BY TheDate) RowId, 
        ROW_NUMBER() OVER (PARTITION BY UserID,TheType ORDER BY TheDate) PurchaseRowId, 
        * 
    FROM @Test 

), CTE2
AS 
(
    SELECT 
        MIN(A.RowId) MinId,
        MAX(A.RowId) MaxId
    FROM 
        CTE1 A
    GROUP BY    
        A.TheType,
        A.RowId - A.PurchaseRowId
)


SELECT          
    A.UserID ,
    A.TheType ,
    A.TheDate , 
    CASE WHEN B.MinId IS NULL THEN NULL ELSE 'YES' END Result
FROM 
    CTE1 A LEFT JOIN 
    CTE2 B ON A.RowId >= B.MinId AND A.RowId <= B.MaxId AND  (B.MaxId - B.MinId) > 2    
    --AND A.TheType = 'Purchase'    
ORDER BY A.TheDate

结果:

UserID      TheType    TheDate                   Result
----------- ---------- ----------------------- - ------
1234        Bonus      2017-06-06 11:06:03.130   NULL
1234        Purchase   2017-06-07 11:06:03.130   NULL
1234        Bonus      2017-06-08 11:06:03.130   NULL
1234        Purchase   2017-06-09 11:06:03.130   YES
1234        Purchase   2017-06-10 11:06:03.130   YES
1234        Purchase   2017-06-11 11:06:03.130   YES
1234        Purchase   2017-06-12 11:06:03.130   YES
1234        Bonus      2017-06-13 11:06:03.130   NULL

答案 1 :(得分:0)

首先,您必须派生列组,然后按原样(具有= 4)和内部联接与原始表进行分组。

drop table if exists #Test;

create table #Test
(
UserID int
, TheType varchar(10)
, TheDate date
, Result varchar(10)
);

insert into #Test
select 1234, 'Bonus', getdate(), null
union
select 1234, 'Purchase', getdate() - 1, null
union
select 1234, 'Purchase', getdate() - 2, null
union
select 1234, 'Purchase', getdate() - 3, null
union
select 1234, 'Purchase', getdate() - 4, null
union
select 1234, 'Bonus', getdate() - 5, null
union
select 1234, 'Purchase', getdate() - 6, null
union
select 1234, 'Bonus', getdate() - 7, null;

drop table if exists #temp;

select
     *
   , lag(t.TheDate, 1) over ( order by t.TheDate ) as Lag01
   , lag(t.TheType, 1) over ( order by t.TheDate ) as LagType
into
     #temp
from #Test t;

with cteHierarchy
as
(
    select
          UserID
        , TheType
        , TheDate
        , Result
        , Lag01
        , t.TheDate as Root
    from  #temp t
    where t.LagType <> t.TheType
    union all
    select
         t.UserID
       , t.TheType
       , t.TheDate
       , t.Result
       , t.Lag01
       , cte.Root as Root
    from #temp t
         inner join cteHierarchy cte on t.Lag01 = cte.TheDate
                                        and t.TheType = cte.TheType
)
update test
set
    Result = 4
from (
    select
        t.Root
        , count(t.UserID) as Cnt
        , t.UserID
    from cteHierarchy t
    group by t.UserID, t.Root
    having count(t.UserID) = 4
) tt
    inner join #Test test on tt.UserID = test.UserID


select * from #Test t
order by t.TheDate;