sqlserver開窗函式改造樣例

2022-02-13 06:16:54 字數 4738 閱讀 6862

作乙個查詢的效能優化。

先清快取

dbcc dropcleanbuffers

dbcc freeproccache

原查詢 前人遺留。

1

declare

@total

float,@total_person

float,@times_person

float,@date

varchar(50) 2

select

@date

=convert(char(10),getdate(),120) 3

4select

@total

=sum(price*person)*

1.0from db_time t inner

join db_movie m on t.movieid=m.id inner

join db_cinema c on t.cinemaid=

c.id

5where

cast(showdate as date)=

'2014-02-27

'and t.sta=16

7select

@times_person

=sum(1) from db_time t inner

join db_movie m on t.movieid=m.id inner

join db_cinema c on t.cinemaid=

c.id

8where

cast(showdate as date)=

'2014-02-27

'and t.sta=19

10select

@total_person

=sum(person) from db_time t inner

join db_movie m on t.movieid=m.id inner

join db_cinema c on t.cinemaid=

c.id

11where

cast(showdate as date)=

'2014-02-27

'and t.sta=1;

1213

with sr as(14

select

15--

row_number() over(order by sum(price*person) desc) as 'index'

16--,17

movieid id

18,m.name name

19,m.enname

20 ,sum(price*person)*

1.0as

boxoffice

21 ,sum(price*person)*

1.0/

@total

boxpercent

22 ,sum(1

) showcount

23 ,sum(1)*

1.0/

@times_person

showpercent

24 ,sum

(person) audiencecount

25 ,sum(person)*

1.0/

@total_person

audiencepercent

26 ,cast(round(sum(price*person)*

1.0/

sum(person),0) as

int) price

27--

,sum(person)*1.0/sum(1) as test

28--

,sum(person)*1.0 as t1

29--

,sum(1) as t2

30 ,cast(round(sum(person)*

1.0/

sum(1),0) as

int) as

renci

31 ,round(cast(sum(person) as

float)/

sum(seat),4) as

shangzl

32from db_time t inner

join db_movie m on t.movieid=m.id inner

join db_cinema c on t.cinemaid=

c.id

33where

cast(showdate as date)=

'2014-02-27

'and t.sta=134

group

bymovieid,m.name,m.enname35)

3637

select

*from sr order

by boxoffice desc

執行時間18s

最開始想著是把上面3條求總量的查詢改成在一條裡完成,where條件重複多次,想想開脆改成開窗函式好了

經開窗函式改造後的查詢。

1

with sr as(2

select

3distinct4--

row_number() over(order by sum(price*person) desc) as 'index'5--

,6movieid id

7,m.name name

8,m.enname

9 ,(sum(price*person) over(partition by movieid))*

1.0as

boxoffice

10 ,(sum(price*person) over(partition by movieid))*

1.0/(sum(price*person) over()) as

boxpercent

11 ,sum(1) over(partition by movieid) as

showcount

12 ,(sum(1) over(partition by movieid))*

1.0/(sum(1) over

()) showpercent

13 ,sum(person) over(partition by

movieid) audiencecount

14 ,((sum(person) over(partition by movieid))*

1.0)/((sum(person) over

())) audiencepercent

15 ,cast(round((sum(price*person) over(partition by movieid))*

1.0/(sum(person) over(partition by movieid)),0) as

int) price

16 ,cast(round(((sum(person) over(partition by movieid))*

1.0/(count(0) over(partition by movieid))),0) as

int) as

renci

17 ,round(cast((sum(person) over(partition by movieid)) as

float)/(sum(seat) over(partition by movieid)),4) as

shangzl

18from db_time t inner

join db_movie m on t.movieid=m.id inner

join db_cinema c on t.cinemaid=

c.id

19where

cast(showdate as date)=

'2014-02-27

'and t.sta=120

)21select

*from sr order

by boxoffice desc

**確實精簡不少,同樣的where子句消除了。(兩個查詢中的rownumber完全沒用,注掉了)

執行時間17s,心裡隱隱期待的是查詢時間有明顯減少,實際查詢時間在誤差範圍內,基本未變化,看來開發開窗函式的目的不是為效能提公升,而是為了方便開發人員編寫查詢**,減少查詢難度,提高查詢可讀性。

查詢計畫有很大變化,經開窗函式改造後的查詢計畫,多了很多「表假離線」的執行步驟

但兩種查詢最耗時的依然是97%聚集索引掃瞄(表上只有id的自增聚集索引)

rank 開窗函式 排序類開窗函式

1,row number over 排序,連續 select score,row number over from sc 按原始 的成績順序進行排序 原始 成績順序 先將分數從大到小排序,分數相同,排名不同 select score,row number over order by score fr...

oracle開窗函式

1.使用row number分頁,查詢第1 10條資料 select t.custid,t.companyname,t.address,t.city from select row number over order by custid as rownum,custid,companyname,ad...

開窗函式簡介

比如我們想查詢每個工資小於5000元的員工資訊 城市以及年齡 並且在每行中都顯示所有工資小於5000元的員工個數,執行下面的sql語句 這個語句顯然是錯誤的,因為count 是聚合函式,然後fname和fage欄位沒有包含分組裡面。那麼,這樣寫呢?sql view plain copy select...