簡體   English   中英

查找具有 3 個或更多具有相同值的連續記錄的記錄

[英]Find records with 3 or more consecutive records with same value

我在包含日期、客戶編號、交易類型和價值的表中有一個日期交易列表。 如果該客戶按日期排序時連續有 3 次或更多連續的“現金”交易,我需要返回該客戶的所有交易。

因此,在下面的示例數據中,我想返回客戶 1 和 3 的所有交易(包括信用交易),因為這兩個客戶連續進行了 3 次或更多現金交易。 客戶 2 被忽略,因為即使他們有超過 3 筆現金交易,它們也不是連續的。

╔════════════╦════════════╦═══════════╦═══════╗
║  Customer  ║    Date    ║ TransType ║ Value ║
╠════════════╬════════════╬═══════════╬═══════╣
║ Customer 1 ║ 1/01/2015  ║ cash      ║ 23.00 ║
║ Customer 1 ║ 2/01/2015  ║ cash      ║ 24.00 ║
║ Customer 2 ║ 2/01/2015  ║ cash      ║ 28.00 ║
║ Customer 2 ║ 4/01/2015  ║ credit    ║ 29.00 ║
║ Customer 3 ║ 5/01/2015  ║ credit    ║ 27.00 ║
║ Customer 2 ║ 6/01/2015  ║ cash      ║ 23.00 ║
║ Customer 2 ║ 8/01/2015  ║ credit    ║ 24.00 ║
║ Customer 3 ║ 9/01/2015  ║ cash      ║ 28.00 ║
║ Customer 3 ║ 13/01/2015 ║ cash      ║ 29.00 ║
║ Customer 1 ║ 15/01/2015 ║ cash      ║ 25.00 ║
║ Customer 1 ║ 17/01/2015 ║ credit    ║ 26.00 ║
║ Customer 3 ║ 18/01/2015 ║ cash      ║ 23.00 ║
║ Customer 1 ║ 20/01/2015 ║ cash      ║ 27.00 ║
║ Customer 3 ║ 20/01/2015 ║ credit    ║ 24.00 ║
║ Customer 2 ║ 21/01/2015 ║ cash      ║ 25.00 ║
║ Customer 3 ║ 22/01/2015 ║ credit    ║ 25.00 ║
║ Customer 2 ║ 23/01/2015 ║ cash      ║ 26.00 ║
╚════════════╩════════════╩═══════════╩═══════╝

因此,要獲得至少有三筆連續現金交易的客戶,您可以使用自聯接,並為每一行連接前后的行並測試所有三筆交易是否都是現金交易。

用作第一個公共表表達式的查詢對按客戶分區的所有行進行編號,因此我們有一個合適的列來連接它們。 然后在第二個公用表表達式中建立連接,並將其結果饋送到最終查詢中。 查詢可以縮短,但為了清楚起見,我把它留得更長一點。

with cte as (
    select *, r = row_number() over (partition by customer order by date) 
    from table1 -- this is your source table
), cte2 as (
    select t1.customer 
    from cte t1
    join cte t2 on t1.customer = t2.customer and (t1.r = t2.r-1 or t1.r = t2.r+1)
    where t1.transtype = 'cash' and t2.transtype = 'cash'
    group by t1.customer
    having count(*) >= 3
)

select * from Table1 -- this is your source table
where Customer in (select Customer from cte2)
order by customer, date;

使用您的示例數據,這將返回客戶 1 和 3 的所有行。

示例 SQL 小提琴

您可以使用一個技巧來枚舉“現金”交易。 這個技巧是行號的差異,非常有用:

select t.*
from (select t.*, count(*) over (partition by grp, customerid, transtype) as cnt
      from (select t.*,
                   (row_number() over (partition by customerid order by date) -
                    row_number() over (partition by customerid, transtype order by date)
                   ) as grp
            from t
           ) t
      where transtype = 'cash'
     ) t
where cnt >= 3;

這將返回客戶和開始日期。 如果要返回實際交易,可以使用附加級別的窗口函數:

select customerid, min(date) as start_date, sum(value) as sumvalue
from (select t.*,
             (row_number() over (partition by customerid order by date) -
              row_number() over (partition by customerid, transtype order by date)
             ) as grp
      from t
     ) t
where transtype = 'cash'
group by grp, transtype, customerid
having count(*) >= 3;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM