我在表格中列出了日期,交易类型和价值。如果该客户有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 ║ ╚════════════╩════════════╩═══════════╩═══════╝
答案 0 :(得分:1)
因此,为了让拥有至少三个连续现金交易的客户可以使用自我加入,并且每行连接前后行,并测试这三个是否为现金转换。
用作第一个公用表表达式的查询对客户分区的所有行进行编号,因此我们有一个合适的列来连接它们。然后在第二个公用表表达式中建立连接,并将其结果输入到最终查询中。查询可以缩短,但为了清晰起见,我把它留了一点。
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的所有行。
答案 1 :(得分:1)
您可以使用技巧来枚举"现金"交易。这个技巧是行数的差异,它非常有用:
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_nubmer() 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_nubmer() over (partition by customerid, transtype order by date)
) as grp
from t
) t
where transtype = 'cash'
group by grp, transtype, customerid
having count(*) >= 3;