亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

SQL語句-計算中間值

系統(tǒng) 2277 0

問題:計算一列數(shù)字值的中間值(中間值就是一組有序元素中間成員的值)。例如,查找DEPTNO 20中工資的中間數(shù)。如下列工資:

select sal

?? from emp

where deptno = 20

order by sal

??????? SAL

----------

??????? 800

?????? 1100

?????? 2975

?????? 3000

?????? 3000

中間數(shù)為2975。

解決方案

除了Oracle解決方案(用函數(shù)計算中間數(shù))之外,其他所有解決方案都是以Rozenshtein、Abramovich和Birger在 Optimizing Transact-SQL: Advanced Programming Techniques (SQL Forum Press, 1997)中描述的方法為基礎(chǔ)的。與傳統(tǒng)的自聯(lián)接相比,窗口函數(shù)的引入,使解決方案更為有效。

DB2

使用窗口函數(shù)COUNT(*) OVER和ROW_NUMBER,查找中間數(shù):

1?? select avg(sal)

2???? from (

3?? select sal,

4????????? count(*) over() total,

5????????? cast(count(*) over() as decimal)/2 mid,

6????????? ceil(cast(count(*) over() as decimal)/2) next,

7????????? row_number() over (order by sal) rn

8???? from emp

9??? where deptno = 20

10????????? ) x

11??? where ( mod(total,2) = 0

12??????????? and rn in ( mid, mid+1 )

13????????? )

14?????? or ( mod(total,2) = 1

15??????????? and rn = next

16????????? )

MySQL和PostgreSQL

使用自聯(lián)接查找中間數(shù):

1?? select avg(sal)

2???? from (

3?? select e.sal

4???? from emp e, emp d

5??? where e.deptno = d.deptno

6????? and e.deptno = 20

7??? group by e.sal

8?? having sum(case when e.sal = d.sal then 1 else 0 end)

9???????????????????????????? >= abs(sum(sign(e.sal - d.sal)))

10????????? )

Oracle

使用函數(shù)MEDIAN(Oracle Database 10g)或PERCENTILE_CONT(Oracle9i Database):

1 select median (sal)

2??? from emp

3?? where deptno=20

1 select percentile_cont(0.5)

2????????? within group(order by sal)

3??? from emp

4?? where deptno=20

對于Oracle8i Database,使用DB2解決方案。對于Oracle8i Database之前的版本,可以采用PostgreSQL/MySQL解決方案。

SQL Server

使用窗口函數(shù)COUNT(*) OVER和ROW_NUMBER,可得到中間數(shù):

1?? select avg(sal)

2???? from (

3?? select sal,

4????????? count(*)over() total,

5????????? cast(count(*)over() as decimal)/2 mid,

6????????? ceiling(cast(count(*)over() as decimal)/2) next,

7????????? row_number()over(order by sal) rn

8???? from emp

9??? where deptno = 20

10????????? ) x

11??? where ( total%2 = 0

12??????????? and rn in ( mid, mid+1 )

13????????? )

14?????? or ( total%2 = 1

15??????????? and rn = next

16????????? )

討論

DB2和SQL Server

DB2和SQL Server 解決方案的唯一差別是語法的稍許不同:SQL Server用“%”求模,而DB2使用MOD函數(shù);其余的都相同。內(nèi)聯(lián)視圖X返回三個不同的計數(shù)值,TOTAL、MID和NEXT,還用到由 ROW_NUMBER生成的RN。這些附加列有助于求解中間數(shù)。檢驗內(nèi)聯(lián)視圖X的結(jié)果集,就會看到這些列表示的意義:

select sal,

??????? count(*)over() total,

??????? cast(count(*)over() as decimal)/2 mid,

??????? ceil(cast(count(*)over() as decimal)/2) next,

??????? row_number()over(order by sal) rn

?? from emp

where deptno = 20

SAL TOTAL?? MID NEXT??? RN

---- ----- ---- ---- ----

800????? 5?? 2.5???? 3???? 1

1100????? 5?? 2.5???? 3???? 2

2975????? 5?? 2.5???? 3???? 3

3000????? 5?? 2.5???? 3???? 4

3000????? 5?? 2.5???? 3???? 5

要得到中間數(shù),一定要把SAL值由低到高排序。由于DEPTNO 20中的職員數(shù)是奇數(shù),因此它的中間數(shù)就是其RN與NEXT相等的SAL(即大于職員總數(shù)除以2的最小整數(shù))。

如果結(jié)果集返回奇數(shù)行,WHERE子句的第一部分(第11~13行)條件不滿足。如果能夠確定結(jié)果集是奇數(shù)行,則可以簡化為:

select avg(sal)

?? from (

select sal,

??????? count(*)over() total,

??????? ceil(cast(count(*)over() as decimal)/2) next,

??????? row_number()over(order by sal) rn

?? from emp

where deptno = 20

??????? ) x

where rn = next

令人遺憾的是,如果結(jié)果集包含偶數(shù)行,上述簡化的解決方案就行不通。在最初的解決方案中,采用MID列中的值處理偶數(shù)行。想想DEPTNO 30的內(nèi)聯(lián)視圖X的結(jié)果會怎樣,該部門有6名職員:

select sal,

??????? count(*)over() total,

??????? cast(count(*)over() as decimal)/2 mid,

??????? ceil(cast(count(*)over() as decimal)/2) next,

??????? row_number()over(order by sal) rn

?? from emp

where deptno = 30

SAL TOTAL?? MID NEXT??? RN

---- ----- ---- ---- ----

950????? 6???? 3???? 3???? 1

1250????? 6???? 3???? 3???? 2

1250????? 6???? 3???? 3???? 3

1500????? 6???? 3???? 3???? 4

1600????? 6???? 3???? 3???? 5

2850????? 6???? 3???? 3???? 6

由于返回了偶數(shù)行,則采用下述方式計算中間數(shù):計算RN分別等于MID和MID + 1兩行的平均數(shù)。

MySQL和PostgreSQL

根據(jù)第一個自聯(lián)接表EMP計算中間數(shù),而該表返回了所有工資的笛卡兒積(GROUP BY??? E.SAL會去掉重復(fù)值)。HAVING子句使用函數(shù)SUM計算E.SAL等于D.SAL的次數(shù);如果這個值大于等于E.SAL且大于D.SAL次數(shù),那 么該行就是中間數(shù)。在SELECT列表中加入SUM就可以觀察到這種情況:

select e.sal,

??????? sum(case when e.sal=d.sal

???????????????? then 1 else 0 end) as cnt1,

??????? abs(sum(sign(e.sal - d.sal))) as cnt2

?? from emp e, emp d

where e.deptno = d.deptno

??? and e.deptno = 20

group by e.sal

SAL CNT1 CNT2

---- ---- ----

800???? 1???? 4

1100???? 1???? 2

2975???? 1???? 0

3000???? 4???? 6

Oracle

在Oracle Database 10g或Oracle9i Database中,可以使用Oracle提供的函數(shù)計算中間數(shù);對于Oracle8i Database,可以采用DB2解決方案;其他版本必須采用PostgreSQL解決方案。顯然可以用MEDIAN函數(shù)計算中間值,用 PERCENTILE_CONT函數(shù)也可以計算中間值就不那么顯而易見了。傳遞給PERCENTILE_CONT的值0.5是一個百分比值。子句 WITHIN GROUP (ORDER BY SAL)確定PERCENTILE_CONT要搜索哪些有序行(記住,中間值就是一組已排序值的中間值)。返回的值就是搜索的有序行中符合給定百分比(在 這個例子中是0.5,因為其兩個邊界值分別為0和1)的值。

SQL語句-計算中間值


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 四虎avtom影院 | 九九久久视频 | 国产一区二区不卡 | 草草影院国产第一页 | 欧美亚洲天堂 | 日本欧洲亚洲一区在线观看 | 亚洲性一区 | 伊人精品在线视频 | 国产精品伦一区二区三级视频 | 欧美一级看片a免费视频 | 成人午夜毛片在线看 | 天堂国产 | 这里只有久久精品视频 | 97se亚洲国产综合自在线 | 亚洲国产欧洲精品路线久久 | 国产一区二区三区在线免费 | 亚洲一区二区三区四区 | 狠狠色噜噜狠狠狠97影音先锋 | 久久99热精品免费观看k影院 | 国产成人福利在线 | 日韩五月天 | 一区二区三区中文字幕 | 97人人插| 久久成人免费 | 欧美777精品久久久久网 | 国产成人a在一区线观看高清 | 中文一区在线观看 | 在线观看 中文字幕 | 国产永久免费爽视频在线 | 4hu最新 | 成人国产免费 | 欧美在线性爱视频 | 一级生活毛片 | 国产精品亚洲精品日韩已满 | 欧美观看一级毛片 | 久久精品香蕉视频 | 日日射天天操 | 日本亚洲黄色 | 欧美亚洲一区二区三区四 | 天天干天天操天天插 | jiucao视频在线观看 |