2017-12-14 21 views
0

スーパーマーケット内の取引からショッピングバスケットを識別しようとしています。SQL Server SQL - 特定の値またはフラグに基づいてシーケンスをインクリメント

私は顧客IDとトランザクションID、およびアイテムが棚から選択された時間、つまりトランザクションを持っています。私は一種のバスケットIDを持っていますが、それは正確ではありません。私は一日の時間帯が異なるバスケットの取引を見ることができるので、彼らは異なるbasket_idでなければならないことがわかります。それは私が何もできないデータの欠陥です。

1つのトランザクションと別のトランザクションの違いが20分を超える場合は、それは別のバスケットです。私はSQLのラグ関数を使ってこれを行います。

トランザクションに値1のフラグを追加します(この時間は20分より長くなります)。だから私は実際に1 +バスケットになるバスケットIDを持っています。

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

お返事ありがとうございました。私はそれを試してみる。 –

関連する問題