簡體   English   中英

SQL Server - 使用窗口函數優化 CTE/子查詢性能

[英]SQL Server - CTE/Subqueries performance optimization with window functions

我用 CTE 得到了我想要的結果,但是有沒有辦法使用窗口函數來獲得相同的結果,從而提高性能?

期望的輸出:

id   date                       Status
141  2015-03-01 00:00:00.000    free --> paid
141  2016-06-01 00:00:00.000    free --> paid
158  2015-08-01 00:00:00.000    free --> paid

CTE代碼:

declare @table01 table (id varchar(3), startdate datetime, enddate datetime, status varchar(10))
insert into @table01 (id, startdate, enddate, status)
values
    ('141','2015-01-01','2015-03-01','free'),
    ('141','2015-03-01','2015-07-01','paid'),
    ('141','2015-07-01','2015-11-01','closed'),
    ('141','2015-11-01','2016-02-01','paid'),
    ('141','2016-02-01','2016-06-01','free'),
    ('141','2016-06-01','2016-10-01','paid'),
    ('141','2016-10-01','2016-12-01','free'),
    ('141','2016-12-01','2017-04-01','closed'),
    ('158','2015-03-01','2015-08-01','free'),
    ('158','2015-08-01','2015-11-01','paid');
------------------------------------------------------------------------------
with sub01 as (
    select id, enddate, status
    from @table01
    where status = 'free'
),
sub02 as (
    select id, startdate, status
    from @table01
    where status = 'paid'
)
select a.id, b.startdate as [date], (a.status + ' --> ' + b.status) as [Status]
from sub01 a
left join sub02 b on a.id = b.id and a.enddate = b.startdate
where a.enddate = b.startdate

如果我理解正確,您可以使用窗口函數:

select id, prev_date, 'free --> paid'
from (select t1.*,
             lag(enddate) over (partition by id order by startdate) as prev_date,
             lag(status) over (partition by id order by startdate) as prev_status
      from table1 t1
     ) t1
where status = 'paid' and prev_status = 'free';

是一個 db<>fiddle。

因為您只對 status = free paid感興趣,並且過渡是在同一天。 它使用case語句( case when status = 'free' then enddate else startdate end )來查找公共日期。 最后只按iddate和條件分組count(*) = 2

這應該會給你更好的表現。

; with cte as
(
    select  id, 
            date    = case when status = 'free' then enddate else startdate end, 
            status
    from    @table01
    where   status in ( 'free', 'paid' )
)
select  id, date, status = 'free --> paid'
from    cte
group by id, date
having count(*) = 2
order by id

暫無
暫無

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

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