2017-12-14 15 views
0

슈퍼마켓 트랜잭션에서 쇼핑 바구니를 식별하려고합니다.SQL Server SQL - 특정 값 또는 플래그를 기반으로 증가 시퀀스

나는 고객 ID와 거래 ID 및 품목이 선반에서 선택된 시간 (거래)이 있습니다. 바구니에 일종의 ID가 있지만 정확하지 않습니다. 나는 서로 다른 시간대에있는 바구니에서 거래를 볼 수 있으므로 다른 basket_id가 있어야 함을 알 수 있습니다. 그것은 내가 할 수없는 데이터의 결함입니다.

하나의 거래와 다른 거래의 차이가 20 분을 초과하면 다른 바구니를 볼 수 있습니다. SQL의 Lag 함수를 사용하여이 작업을 수행합니다.

트랜잭션에 20 분보다 큰 값 1의 플래그를 추가합니다. 그래서 나는 바구니 아이디가 실제로 1+ 바구니가 될 것입니다.

어떻게하면 real_basket_id를 만들 수 있습니까?

많은 감사

앤드류

+2

DDL, 샘플 데이터 및 예상 결과를 게시 할 수 있습니까? 나는 당신의 질문을 이해할 수 있는지 잘 모르겠다. 그러면 모든 사람들이 쉽게 답할 수있을 것이다. [T-SQL 질문 게시 방법] (http://www.sqlservercentral.com/articles/Best+Practices/ 61537 /) – Larnu

답변

0

변형로서 당신은 재귀를 사용하려고 할 수 있습니다. 예제를 참조하십시오.

CREATE TABLE #baskets(
    buyer_id int, 
    basket_id int, 
    trans_time datetime 
) 

INSERT #baskets(buyer_id,basket_id,trans_time)VALUES 
(1,11,DATETIMEFROMPARTS(2017,12,14,1,0,0,0)), 
(1,12,DATETIMEFROMPARTS(2017,12,14,1,5,0,0)), 
(1,12,DATETIMEFROMPARTS(2017,12,14,1,15,0,0)), 
(1,13,DATETIMEFROMPARTS(2017,12,14,1,50,0,0)), 
(2,21,DATETIMEFROMPARTS(2017,12,14,2,0,0,0)), 
(2,22,DATETIMEFROMPARTS(2017,12,14,2,45,0,0)) 

SELECT * 
FROM #baskets 
ORDER BY buyer_id,trans_time 

;WITH numBaskCTE AS(
    SELECT 
    buyer_id, 
    basket_id, 
    trans_time, 
    ROW_NUMBER()OVER(PARTITION BY buyer_id ORDER BY trans_time) n 
    FROM #baskets 
), 
checkBaskCTE AS(
    SELECT 
    buyer_id, 
    basket_id, 
    trans_time, 
    n, 
    basket_id real_basket_id, 
    trans_time prev_time 
    FROM numBaskCTE 
    WHERE n=1 

    UNION ALL 

    SELECT 
    n.buyer_id, 
    n.basket_id, 
    n.trans_time, 
    n.n, 
    IIF(DATEDIFF(MINUTE,c.prev_time,n.trans_time)<=20,c.basket_id,n.basket_id), 
    IIF(DATEDIFF(MINUTE,c.prev_time,n.trans_time)<=20,c.prev_time,n.trans_time) prev_time 
    FROM checkBaskCTE c 
    JOIN numBaskCTE n ON n.buyer_id=c.buyer_id AND n.n=c.n+1 
) 
SELECT 
    buyer_id, 
    basket_id, 
    trans_time, 
    real_basket_id 
FROM checkBaskCTE 
ORDER BY buyer_id,trans_time 

DROP TABLE #baskets 

당신이 열 real_basket_id있는 경우에만 새 행 WHERE real_basket_id IS NULL에 대한 업데이 트를 사용할 수 있습니다.

CREATE TABLE #baskets(
    buyer_id int, 
    basket_id int, 
    trans_time datetime, 
    real_basket_id int 
) 

INSERT #baskets(buyer_id,basket_id,trans_time,real_basket_id)VALUES 
(1,10,DATETIMEFROMPARTS(2017,12,12,21,40,0,0),10), 
(1,11,DATETIMEFROMPARTS(2017,12,13,22,30,0,0),11), 
(1,12,DATETIMEFROMPARTS(2017,12,14,1,0,0,0),NULL), 
(1,13,DATETIMEFROMPARTS(2017,12,14,1,5,0,0),NULL), 
(1,13,DATETIMEFROMPARTS(2017,12,14,1,15,0,0),NULL), 
(1,13,DATETIMEFROMPARTS(2017,12,14,1,50,0,0),NULL), 
(2,21,DATETIMEFROMPARTS(2017,12,14,2,0,0,0),NULL), 
(2,22,DATETIMEFROMPARTS(2017,12,14,2,45,0,0),NULL), 
(3,30,DATETIMEFROMPARTS(2017,12,12,21,40,0,0),30), 
(3,31,DATETIMEFROMPARTS(2017,12,14,0,54,0,0),31), 
(3,32,DATETIMEFROMPARTS(2017,12,14,1,0,0,0),NULL), 
(3,33,DATETIMEFROMPARTS(2017,12,14,1,5,0,0),NULL) 


SELECT * 
FROM #baskets 
WHERE real_basket_id IS NULL -- only new rows 
ORDER BY buyer_id,trans_time 

;WITH numBaskCTE AS(
    -- all new transactions + one last transaction for each buyers 
    SELECT 
    buyer_id, 
    basket_id, 
    real_basket_id, 
    trans_time, 
    ROW_NUMBER()OVER(PARTITION BY buyer_id ORDER BY trans_time) n 
    FROM 
    (
     SELECT *,LEAD(real_basket_id)OVER(PARTITION BY buyer_id ORDER BY trans_time) next_real_basket_id 
     FROM #baskets 
    ) q 
    WHERE next_real_basket_id IS NULL 
), 
checkBaskCTE AS(
    SELECT 
    buyer_id, 
    basket_id, 
    trans_time, 
    n, 
    ISNULL(real_basket_id,basket_id) real_basket_id, 
    trans_time prev_time, 
    IIF(real_basket_id IS NULL,1,0) is_new_row 
    FROM numBaskCTE 
    WHERE n=1 

    UNION ALL 

    SELECT 
    n.buyer_id, 
    n.basket_id, 
    n.trans_time, 
    n.n, 
    IIF(DATEDIFF(MINUTE,c.prev_time,n.trans_time)<=20,c.basket_id,n.basket_id), 
    IIF(DATEDIFF(MINUTE,c.prev_time,n.trans_time)<=20,c.prev_time,n.trans_time) prev_time, 
    1 is_new_row 
    FROM checkBaskCTE c 
    JOIN numBaskCTE n ON n.buyer_id=c.buyer_id AND n.n=c.n+1 
) 
UPDATE b 
SET 
    b.real_basket_id=q.real_basket_id 
FROM #baskets b 
JOIN 
    (
    SELECT 
     buyer_id, 
     basket_id, 
     trans_time, 
     real_basket_id 
    FROM checkBaskCTE 
    WHERE is_new_row=1 
) q 
ON b.buyer_id=q.buyer_id AND b.trans_time=q.trans_time 

SELECT * 
FROM #baskets 
ORDER BY buyer_id,trans_time 

DROP TABLE #baskets 
+0

답장을 보내 주셔서 감사합니다. 나는 그것을 시도 할 것이다. –