日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

使用 FOR XML PATH 合并SQL Server查询结果的重复行

發(fā)布時間:2025/7/25 asp.net 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用 FOR XML PATH 合并SQL Server查询结果的重复行 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

參考資料:

http://www.cnblogs.com/doubleliang/archive/2011/07/06/2098775.html

http://www.cnblogs.com/codeyu/archive/2010/05/25/1743474.html

核心摘要

FOR XML PATH 的作用是把結(jié)果以xml文本的形式顯示出來,也就是說,最終結(jié)果就是一個字符串,因此我們就不需要使用什么字符串合并函數(shù)了。

STUFF函數(shù)的原型是?Stuff(str1, start, len, str2),作用是,刪掉str1中start開始的len個字符,用str2替換。因此,可以起到在多個項之間插入分隔符。

比如,

select ','+name from student for xml path('') group by class

輸出結(jié)果可能是

,Jim,Kate,Tom,Sally

如果使用STUFF,可以刪掉第一個空格

stuff(select ','+name from student for xml path('') group by class, 1, 1, '')

?

原文內(nèi)容

-------------參考------------------------

----假設我們有如下數(shù)據(jù)表
------菜系表------------
--店名??????? 菜系------
--澳門豆撈??? 川菜?
--澳門豆撈??? 粵菜?
--澳門豆撈??? 閩菜?
--為民大酒店? 魯菜?
--為民大酒店? 粵菜?
--為民大酒店? 川菜
-----------------------

-------執(zhí)行如下語句
select?店名,菜系=STUFF((select?','+ltrim(菜系)?from?菜系表?where?店名=t.店名?for?XML path('')),1,1,'')
from?菜系表 t
group?by?店名

-------結(jié)果如下-------------
--店名??????? 菜系----------
--澳門豆撈??? 川菜,閩菜,粵菜
--為民大酒店? 川菜,魯菜,粵菜
----------------------------

--------------------------------------------------------------------------------------
Stuff(expression1_Str,startIndex,lengthInt,expression2_Str)函數(shù)共有四個參數(shù),
其功能是將expression1_Str中自startIndex位置起刪除lengthInt個字符,然后將expression2插入到expression1_Str中的startIndex位置。startIndex 從1開始
數(shù)據(jù)庫表中有三個字段,要以xxxx-xxxxxx-xxxxxx的格式輸出,其中不滿相應位數(shù)的,在后面補空格,即把類似23,1234,879這樣的三個數(shù)以如下形式輸出到報表中:23__-1234__-879___的格式輸出,標注顏色的下劃線一種顏色代表一個空格。?
STUFF(SPACE(4),1,LEN(‘23’),’23’)+’-’+STUFF(SPACE(6),1,LEN(‘1234’),’1234’)+’-’+?STUFF(SPACE(6),1,LEN(‘879’),’879’),轉(zhuǎn)換結(jié)果自然就為23__-1234__-879___了。
Stuff函數(shù)另一種解釋
select?stuff('string1',<starting position>,<length?to?delete?from?string?1>,'string2')
示例:
select?stuff('youxiaofeng',2,1,'F')
從第二個字符開始,刪掉一個字符,然后用'F'代替刪掉字符的位置,如果不需要刪掉字符,則將<length?to?delete?from?string?1>設為0即可。
注意:如果<starting position>或<length?to?delete?from?string?1?>是負的,或者<starting position>是大于<string?1>長度的數(shù),則STUFF函數(shù)將返回NULL,如果指令的<length?to?delete?from?string?1>長于從<starting position>位置到<string?1>結(jié)尾的字符數(shù),此函數(shù)將<string?1?>在<starting position-1>處截斷

---------------------------------------------------------------------------
FOR?XML PATH 語句的應用
大家都知道在SQL Server中利用?FOR?XML PATH 語句能夠把查詢的數(shù)據(jù)生成XML數(shù)據(jù),下面是它的一些應用示例。

DECLARE?@TempTable?table(UserID?int?, UserName?nvarchar(50));
insert?into?@TempTable?(UserID,UserName)?values?(1,'a')
insert?into?@TempTable?(UserID,UserName)?values?(2,'b')

select?UserID,UserName?from?@TempTable?FOR?XML PATH
運行這段腳本,將生成如下結(jié)果:

<row>
<UserID>1</UserID>
<UserName>a</UserName>
</row>
<row>
<UserID>2</UserID>
<UserName>b</UserName>
</row>
大家可以看到兩行數(shù)據(jù)生成了兩個節(jié)點,修改一下PATH的參數(shù):

select?UserID,UserName?from?@TempTable?FOR?XML PATH('lzy')
再次運行上述腳本,將生成如下的結(jié)果:

<lzy>
<UserID>1</UserID>
<UserName>a</UserName>
</lzy>
<lzy>
<UserID>2</UserID>
<UserName>b</UserName>
</lzy>
可以看到節(jié)點變成,其實PATH() 括號內(nèi)的參數(shù)是控制節(jié)點名稱的,這樣的話大家可以看一下如果是空字符串(不是沒有參數(shù))會是什么結(jié)果?

select?UserID,UserName?from?@TempTable?FOR?XML PATH('')
執(zhí)行上面這段腳本將生成結(jié)果:

<UserID>1</UserID>
<UserName>a</UserName>
<UserID>2</UserID>
<UserName>b</UserName>
這樣就不顯示上級節(jié)點了,大家知道在 PATH 模式中,列名或列別名被作為 XPath 表達式來處理,也就是說,是列的名字,這樣大膽試驗一下不給指定列名和別名會是怎么樣?

select?CAST(UserID?AS?varchar)?+?'',UserName?+?''?from?@TempTable?FOR?XML PATH('')
運行上面這句將生成結(jié)果

1a2b

所有數(shù)據(jù)都生成一行,而且還沒有連接字符,這樣的數(shù)據(jù)可能對大家沒有用處,還可以再變化一下:

select?CAST(UserID?AS?varchar)?+?',',UserName?+?'',';'?from?@TempTable?FOR?XML PATH('')
生成結(jié)果

1,a;2,b;

大家現(xiàn)在明白了吧,可以通過控制參數(shù)來生成自己想要的結(jié)果,例如:

select?'{'?+?CAST(UserID?AS?varchar)?+?',','"'?+UserName?+?'"','}'?from?@TempTable?FOR?XML PATH('')
生成結(jié)果

{1,"a"}{2,"b"}

還可以生成其他格式,大家可以根據(jù)自己需要的格式進行組合。

下面是一個數(shù)據(jù)統(tǒng)計的應用,希望大家可以通過下面的實例想到更多的應用

DECLARE?@T1?table(UserID?int?, UserName?nvarchar(50),CityName?nvarchar(50));
insert?into?@T1?(UserID,UserName,CityName)?values?(1,'a','上海')
insert?into?@T1?(UserID,UserName,CityName)?values?(2,'b','北京')
insert?into?@T1?(UserID,UserName,CityName)?values?(3,'c','上海')
insert?into?@T1?(UserID,UserName,CityName)?values?(4,'d','北京')
insert?into?@T1?(UserID,UserName,CityName)?values?(5,'e','上海')

SELECT?B.CityName,LEFT(UserList,LEN(UserList)-1)?FROM?(
SELECT?CityName,
(SELECT?UserName+','?FROM?@T1?WHERE?CityName=A.CityName?FOR?XML PATH(''))?AS?UserList
FROM?@T1?A?
GROUP?BY?CityName
) B
生成結(jié)果(每個城市的用戶名)

北京 b,d
上海 a,c,e

?

靈活運用 SQL SERVER FOR XML PATH

??????? FOR XML PATH 有的人可能知道有的人可能不知道,其實它就是將查詢結(jié)果集以XML形式展現(xiàn),有了它我們可以簡化我們的查詢語句實現(xiàn)一些以前可能需要借助函數(shù)活存儲過程來完成的工作。那么以一個實例為主.

????????一.FOR XML PATH 簡單介紹

?????????????那么還是首先來介紹一下FOR XML PATH ,假設現(xiàn)在有一張興趣愛好表(hobby)用來存放興趣愛好,表結(jié)構(gòu)如下:

???????接下來我們來看應用FOR XML PATH的查詢結(jié)果語句如下:

SELECT*FROM@hobbyFORXML?PATH

?????? 結(jié)果:

<row>
??<hobbyID>1</hobbyID>
??<hName>爬山</hName>
</row>
<row>
??<hobbyID>2</hobbyID>
??<hName>游泳</hName>
</row>
<row>
??<hobbyID>3</hobbyID>
??<hName>美食</hName>
</row>

????? 由此可見FOR XML PATH 可以將查詢結(jié)果根據(jù)行輸出成XML各式!

????? 那么,如何改變XML行節(jié)點的名稱呢?代碼如下:?????

SELECT*FROM@hobbyFORXML?PATH('MyHobby')

?

????? 結(jié)果一定也可想而知了吧?沒錯原來的行節(jié)點<row> 變成了我們在PATH后面括號()中,自定義的名稱<MyHobby>,結(jié)果如下:

<MyHobby>
??<hobbyID>1</hobbyID>
??<hName>爬山</hName>
</MyHobby>
<MyHobby>
??<hobbyID>2</hobbyID>
??<hName>游泳</hName>
</MyHobby>
<MyHobby>
??<hobbyID>3</hobbyID>
??<hName>美食</hName>
</MyHobby>

????? 這個時候細心的朋友一定又會問那么列節(jié)點如何改變呢?還記的給列起別名的關鍵字AS嗎?對了就是用它!代碼如下:

SELECThobbyID?as'MyCode',hName?as'MyName'FROM@hobbyFORXML?PATH('MyHobby')

?

????? 那么這個時候我們列的節(jié)點名稱也會編程我們自定義的名稱 <MyCode>與<MyName>結(jié)果如下: <MyHobby>
??<MyCode>1</MyCode>
??<MyName>爬山</MyName>
</MyHobby>
<MyHobby>
??<MyCode>2</MyCode>
??<MyName>游泳</MyName>
</MyHobby>
<MyHobby>
??<MyCode>3</MyCode>
??<MyName>美食</MyName>
</MyHobby> ??? 噢! 既然行的節(jié)點與列的節(jié)點我們都可以自定義,我們是否可以構(gòu)建我們喜歡的輸出方式呢?還是看代碼:? SELECT'[?'+hName+']'FROM@hobbyFORXML?PATH('')

??? 沒錯我們還可以通過符號+號,來對字符串類型字段的輸出格式進行定義。結(jié)果如下:

[?爬山?][?游泳?][?美食?]

??? 那么其他類型的列怎么自定義? 沒關系,我們將它們轉(zhuǎn)換成字符串類型就行啦!例如:

SELECT'{'+STR(hobbyID)+'}','[?'+hName+']'FROM@hobbyFORXML?PATH('')

??? 好的 FOR XML PATH就基本介紹到這里吧,更多關于FOR XML的知識請查閱幫助文檔!

??? 接下來我們來看一個FOR XML PATH的應用場景吧!那么開始吧。。。。。。

??????? 二.一個應用場景與FOR XML PATH應用

????????首先呢!我們在增加一張學生表,列分別為(stuID,sName,hobby),stuID代表學生編號,sName代表學生姓名,hobby列存學生的愛好!那么現(xiàn)在表結(jié)構(gòu)如下:

???????????

??????? 這時,我們的要求是查詢學生表,顯示所有學生的愛好的結(jié)果集,代碼如下:

SELECTB.sName,LEFT(StuList,LEN(StuList)-1)?ashobby?FROM(
SELECTsName,
(SELECThobby+','FROMstudent?
??WHEREsName=A.sName?
??FORXML?PATH(''))?ASStuList
FROMstudent?A?
GROUPBYsName
)?B?

???????? 結(jié)果如下:

?分析:?好的,那么我們來分析一下,首先看這句:

SELECThobby+','FROMstudent?
??WHEREsName=A.sName?
??FORXML?PATH('')

這句是通過FOR XML PATH 將某一姓名如張三的愛好,顯示成格式為:“ 愛好1,愛好2,愛好3,”的格式!

那么接著看:

SELECTB.sName,LEFT(StuList,LEN(StuList)-1)?ashobby?FROM(
SELECTsName,
(SELECThobby+','FROMstudent?
??WHEREsName=A.sName?
??FORXML?PATH(''))?ASStuList
FROMstudent?A?
GROUPBYsName
)?B??

剩下的代碼首先是將表分組,在執(zhí)行FOR XML PATH 格式化,這時當還沒有執(zhí)行最外層的SELECT時查詢出的結(jié)構(gòu)為:

可以看到StuList列里面的數(shù)據(jù)都會多出一個逗號,這時隨外層的語句:SELECT?B.sName,LEFT(StuList,LEN(StuList)-1)?as?hobby??就是來去掉逗號,并賦予有意義的列明!

好啦,太晚啦就說到這里吧!

?

?

?

?

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/dabaopku/archive/2012/07/18/2597237.html

總結(jié)

以上是生活随笔為你收集整理的使用 FOR XML PATH 合并SQL Server查询结果的重复行的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。