在實際項目中,有時會碰到數據庫SQL的特殊排序需求,舉幾個例子,作為參考。
1、自定義優先級
一種常見的排序需求是指定某個字段取值的優先級,根據指定的優先級展示排序結果。比如如下表:
Create TABLE Fruit (id INT IDENTITY(1, 1) ,Name VARCHAR(50));INSERT INTO Fruit (Name) VALUES ('Apple');
INSERT INTO Fruit (Name) VALUES ('Watermelon');
INSERT INTO Fruit (Name) VALUES ('Strawberry');
INSERT INTO Fruit (Name) VALUES ('Banana');
INSERT INTO Fruit (Name) VALUES ('Pear');
如果按照Name字段排序,結果是
Apple
Banana
Pear
Strawberry
Watermelon
如果想把某個字段優先級提高,用如下方法:
select name from fruit
order by case name when 'Strawberry' then 1when 'Banana' then 2when 'Apple' then 3 else 4
end
指定了Strawberry、Banana、Apple三條記錄的排序優先級,則這三個按照指定的結果排序,其他的都指定為4,排在后面。
Strawberry
Banana
Apple
Watermelon
Pear
如果不指定else 4這句呢,結果如下:
Watermelon
Pear
Strawberry
Banana
Apple
因為不指定就是NULL,在排序中,NULL的優先級最高,排在前面。
2、多字段關聯排序
考慮如下需求:有一個機構表,需要按照深度優先排序,也就是一個機構的下級機構和下下級機構的優先級比同級機構高。
表結構有三個字段:機構號、機構名稱、上級機構號:
branchnum branchname supbranchnum
1 本部 00000
2 北京市分行 00001
3 天津市分行 00001
4 河北省分行 00001
5 山西省分行 00001
2001 北京中關村中心支行 00002
2002 北京王府井支行 00002
2006 北京奧運村支行 00002
2010 北京東城支行 00002
2026 北京西城支行 00002
2044 北京崇文支行 00002
2061 北京宣武支行 00002
2077 北京朝陽支行 00002
2099 北京海淀支行 00002
2135 北京豐臺支行 00002
2137 北京方莊中心支行 00002
2154 北京首都機場支行 00002
2160 北京通州支行 00002
2169 北京大興支行 00002
2175 北京世紀財富中心支 00002
2178 北京順義支行 00002
2185 北京昌平支行 00002
2194 北京平谷支行 00002
2195 北京密云支行 00002
2198 北京懷柔支行 00002
2204 北京延慶支行 00002
2206 北京金融中心支行 00002
2209 北京中銀大廈支行 00002
2210 北京石景山支行 00002
2211 北京商務區支行 00002
2227 北京使館區支行 00002
2228 北京國際貿易中心支 00002
2231 北京上地支行 00002
2232 北京投資廣場支行 00002
2233 北京雅寶路支行 00002
2354 天津大港支行 00003
2361 天津和平支行 00003
2382 天津河西支行 00003
2398 天津南開支行 00003
2412 天津紅橋支行 00003
2423 天津河北支行 00003
2447 天津河東支行 00003
2463 天津津南支行 00003
2470 天津北辰支行 00003
2478 天津東麗支行 00003
2484 天津西青支行 00003
2492 天津武清支行 00003
2500 天津寶坻支行 00003
2504 天津漢沽支行 00003
2508 天津寧河支行 00003
2510 天津薊縣支行 00003
2519 天津靜海支行 00003
2523 天津津鋼支行 00003
2601 石家莊市機場路支行 00004
2626 石家莊市中山支行 00004
2652 石家莊市裕東支行 00004
2678 石家莊市裕華支行 00004
3451 太原鼓樓支行 00005
3479 太原平陽支行 00005
3494 太原并州支行 00005
3506 太原漪汾支行 00005
可以寫一個排序函數,對每一個機構計算它的排序值,排序值就等于上級機構號:
Create FUNCTION fn_compare
(@Branchnum int
)
RETURNS int
AS
BEGINdeclare @returnVal intselect @returnVal=supBranchnum from Branch where Branchnum=@Branchnumif(@returnVal=1)Beginset @returnVal=@BranchnumEndreturn @returnVal
END
GO
然后通過如下語句查詢排序結構:
select branchnum,branchname,supbranchnum from branchorder by dbo.fn_compare(branchnum),branchnum
因為fn_compare函數中,對一個機構和它下級機構返回的排序值(ReturnVal)相等,所以為了使上級機構號排在下級機構前面,需要使用第二個排序字段Branchnum。排序結果如下:
branchnum branchname supbranchnum
1 本部 00000
2 北京市分行 00001
2001 北京中關村中心支行 00002
2002 北京王府井支行 00002
2006 北京奧運村支行 00002
2010 北京東城支行 00002
2026 北京西城支行 00002
2044 北京崇文支行 00002
2061 北京宣武支行 00002
2077 北京朝陽支行 00002
2099 北京海淀支行 00002
2135 北京豐臺支行 00002
2137 北京方莊中心支行 00002
2154 北京首都機場支行 00002
2160 北京通州支行 00002
2169 北京大興支行 00002
2175 北京世紀財富中心支 00002
2178 北京順義支行 00002
2185 北京昌平支行 00002
2194 北京平谷支行 00002
2195 北京密云支行 00002
2198 北京懷柔支行 00002
2204 北京延慶支行 00002
2206 北京金融中心支行 00002
2209 北京中銀大廈支行 00002
2210 北京石景山支行 00002
2211 北京商務區支行 00002
2227 北京使館區支行 00002
2228 北京國際貿易中心支 00002
2231 北京上地支行 00002
2232 北京投資廣場支行 00002
2233 北京雅寶路支行 00002
20170 北京房山支行 00002
3 天津市分行 00001
2354 天津大港支行 00003
2361 天津和平支行 00003
2382 天津河西支行 00003
2398 天津南開支行 00003
2412 天津紅橋支行 00003
2423 天津河北支行 00003
2447 天津河東支行 00003
2463 天津津南支行 00003
2470 天津北辰支行 00003
2478 天津東麗支行 00003
2484 天津西青支行 00003
2492 天津武清支行 00003
2500 天津寶坻支行 00003
2504 天津漢沽支行 00003
2508 天津寧河支行 00003
2510 天津薊縣支行 00003
2519 天津靜海支行 00003
2523 天津津鋼支行 00003
4 河北省分行 00001
2601 石家莊市機場路支行 00004
2626 石家莊市中山支行 00004
2652 石家莊市裕東支行 00004
2678 石家莊市裕華支行 00004
5 山西省分行 00001
3451 太原鼓樓支行 00005
3479 太原平陽支行 00005
3494 太原并州支行 00005
3506 太原漪汾支行 00005