SQL優化之使用數學的方式優化SQL編碼01

2021-10-13 22:59:20 字數 3609 閱讀 1093

筆者最近工作大多寫sql為主。所以在此記錄一下工作中遇到的問題和解決方案。

直接拿最近的乙個需求舉例,樓主習慣先寫自己原先的笨方法,也是大多數人一下子就能想到的方法,然後在去寫改進的方法。

好了,說下具體需求:

輕度彙總後的資料涉及到了標籤打分。根據某列(數值型)的範圍進行劃分並打上相應的標籤,並用該標籤與標籤評分表關聯拿到評分。

看完需求後,簡單啊,開搞。

為了方便,以下資料都用乙個標籤來講。

label(標籤)

grade(等級)

score(分值)

desc( (左閉右開)l1a

1000

前20%l1b

80020%—40%l1c

60040%—60%l1d

40060%—80%l1e

200後20%l1f

0值為0 id

label(標籤)

total_count(該標籤出現的次數)

001l1

390002

l1700

003l1

675004

l15065

首先需要將資料根據百分比將資料的等級標識出來

select  id

,label

,total_count

,rk,cnt

,rk / cnt as percentage

,case

when total_count =

0then

'f'when rk / cnt >

0and rk / cnt <

0.2then

'a'when rk / cnt >=

0.2and rk / cnt <

0.4then

'b'when rk / cnt >=

0.4and rk / cnt <

0.6then

'c'when rk / cnt >=

0.6and rk / cnt <

0.8then

'd'when rk / cnt >=

0.8then

'e'end

as grade

from

(select id

,label

,total_count

,row_number(

)over

(order

by total_count desc

)as rk

,count(*

)over()

as cnt

from table_agg

) t;

結果如下:

idlabel

total_count

rkcnt

_c5grade

004l1

506518

0.125

a007

l1407828

0.25

b002

l170038

0.375

b001

l139048

0.5c

008l1

3355

80.625

d006

l120168

0.75

d005

l19978

0.875

e003l10

881f

然後根據(label, grade) 去關聯標籤評分表即可拿到對應的分值。

如果在0到1區縣化分不只為5個區間呢?有時候為了讓評分更加細粒度,我們可能會在0到1之前劃分為100,500,甚至1000個區間!!

如果按照上面寫case when的方式。。。emmm也挺好,一天啥也不用幹了,泡杯茶cv**。

但是這麼做寫出來的sql別人看了會罵娘,而且也不保證區間的開閉都正確。

最重要的一點那就是:如果我的區間動態調整了,也就是說我的標籤評分表更新了怎麼辦?人工維護嗎???

非也!!下面介紹一種從數學上的方法,讓你的**由幾十行,幾百行都變成短短的一行。

首先,在標籤評分表中,如果我們的區間分為了n個,n > 50 …甚至1000,用大寫字母abc來表示已經很難了。

所以我們換種思路,將grade使用自然公升序數字:1,2,3 … n 來表示,即:

label(標籤)

grade(等級)

score(分值)

desc( (左閉右開)l11

1000

前20%l12

80020%—40%l13

60040%—60%l14

40060%—80%l15

200後20%l16

0值為0

然後重點來了,先把改完的sql列出來:

select  id

,label

,total_count

,rk,cnt

,rk / cnt as percentage

,case

when total_count =

0then

'0'else ceil(

(rk / cnt)*5

)end

as grade

from

(select id

,label

,total_count

,row_number(

)over

(order

by total_count desc

)as rk

,count(*

)over()

as cnt

from table_agg

) t;

得到的結果為:

idlabel

total_count

rkcnt

_c5grade

004l1

506518

0.125

1007

l1407828

0.25

2002

l170038

0.375

2001

l139048

0.53

008l1

3355

80.625

4006

l120168

0.75

4005

l19978

0.875

5003l10

8816

然後根據(label, grade) 去關聯標籤評分表即可拿到對應的分值。

大家看到了,沒錯!重點那就是

case

when total_count =

0then

'0'else ceil(

(rk / cnt)*5

)end

as grade

這裡使用了ceil這個向上取整的函式,而5則是代表了劃分的區間。

至此,用數學方法解決了此類場景下根據百分數多個特定區間劃分的問題。

真是妙蛙種子吃著妙脆角妙進了公尺奇妙妙屋,妙到家了

by 倆只猴

2021.01.04

SQL優化之使用數學的方式動態的確定區間並統計02

今天在群裡看到了乙個小夥伴提的乙個sql需求 把一列分為10個區間,按最大值和最小值去分區間,然後統計區間資料量。emmm,感覺和之前的那篇文章很像,但又有些許不同,而且他這個場景應用更頻繁,所以總結一波。一般的分段區間統計 指定步長的分段區間統計 動態計算步長的分段區間統計 乙個區間的包含左邊界和...

SQL優化之索引使用

最近找工作,遇到乙個面試題 sql哪些關鍵字會忽略索引?因為之前沒這方面的經驗,當時懵逼了,隨便扯了一點。最終有沒能通過面試很遺憾。我們都知道對查詢進行優化,應盡量避免全表掃瞄,多使用索引,首先應考慮在 where 及 order by 涉及的列上建立索引。不過應該注意兩點 1 並不是所有索引對查詢...

sql優化之邏輯優化

在單機資料庫系統中進行優化。面臨的問題,比如說給定乙個要query的sql語句,查詢優化演算法的目標就是找到查詢的乙個具有最小執行花費的執行計畫,如果找到了,那麼這樣的執行計畫一定具有最快的響應時間。查詢語句可表示成一顆二叉樹,其中葉子代表關係,內部結點是運算子,表示左右子樹的連線關係,子樹是sql...