在項目開發中,有時會碰到將列記錄合併爲一行的狀況,例如根據地區將人員姓名合併,或根據拼音首字母合併城市等,下面就以根據地區將人員姓名合併爲例,詳細講一下合併的方法。函數
首先,先建一個表,並添加一些數據,建表代碼以下:測試
If OBJECT_ID(N'Demo') Is Not Null
Begin
Drop Table Demo
End
Else
Begin
Create Table Demo(
Area nvarchar(30),
Name nvarchar(20))spaInsert Into Demo(Area,Name)
Values(N'北京',N'張三'),
(N'上海',N'李四'),
(N'深圳',N'王五'),
(N'深圳',N'錢六'),
(N'北京',N'趙七'),
(N'北京','Tom'),
(N'上海','Amy'),
(N'北京','Joe'),
(N'深圳','Leo')
End
Go3d
建完後查詢一下,可見表中數據以下:blog
若是僅將Name列合併,不遵循任何條件的話,咱們能夠採用兩種方法,第一種就是採用FOR XML PATH方式,代碼以下:開發
SELECT ','+Name FROM dbo.Demo FOR XML PATH('')get
運行結果以下:it
關於FOR XML PATH的詳細介紹可參考MSDN:搭配 FOR XML 使用 PATH 模式io
第二種方法就是定義一個變量用來裝載查詢的結果,代碼以下:function
Declare @NameCollection nvarchar(500)
Select @NameCollection=ISNULL(@NameCollection+',','')+Name From dbo.Demo
Select @NameCollection as NameCollection
運行結果以下:
加了ISNULL是由於最開始變量@NameCollection爲NULL,爲了不「張三」前多一個逗號(「,」)而採用的替換。
上面講了在無條件的狀況下合併一列,可是在項目中幾乎不會遇到這樣的狀況,通常都是根據某一列來合併另外一列的數據,例如咱們如今要根據Area將Name合併,獲得這樣的結果:
有了上面的基礎,要合併成這樣的數據就容易了,咱們只須要針對Area列採用聚合GROUP BY或取不重複值DISTINCT,而後根據Area列合併Name列,有了思路,下面就來講說如何實現,首先仍是採用FOR XML PATH方式,結合自鏈接,首先先按Area列對Name列進行合併,代碼以下:
SELECT Area,
(SELECT ','+Name FROM dbo.Demo WHERE Area = t.Area FOR XML PATH(''))
AS NameCollection FROM dbo.Demo AS t
運行結果以下:
如今有兩點還沒實現,第一是結果重複了,第二是NameCollection列最開始都多了一個逗號,先去掉逗號,採用STUFF 函數來進行替換,代碼修改以下:
SELECT Area,
STUFF((SELECT ','+Name FROM dbo.Demo WHERE Area = t.Area FOR XML PATH('')),1,1,'')
AS NameCollection FROM dbo.Demo AS t
如今運行後結果以下:
下面就剩下去掉重複數據了,分別採用GROUP BY和DISTINCT,代碼以下:
SELECT DISTINCT Area,
STUFF((SELECT ','+Name FROM dbo.Demo WHERE Area = t.Area FOR XML PATH('')),1,1,'')
AS NameCollection FROM dbo.Demo AS t
SELECT Area,
STUFF((SELECT ','+Name FROM dbo.Demo WHERE Area = t.Area FOR XML PATH('')),1,1,'')
AS NameCollection FROM dbo.Demo AS t GROUP BY Area
關於STUFF函數能夠參考MSDN介紹:STUFF函數
運行結果即爲最終咱們須要的結果,最開始在上面講到了一種用變量來裝載查詢結果實現合併一列的方法,下面詳細介紹如何採用上述方法來實現咱們的需求,咱們能夠根據上面的方法建一個函數,傳入一個Area參數,根據Area來進行合併,返回合併值,函數以下:
CREATE FUNCTION MergeByColumn
(
-- Add the parameters for the function here
@Area nvarchar(30)
)
RETURNS nvarchar(500)
AS
BEGIN
-- Declare the return variable here
DECLARE @NC nvarchar(500)-- Add the T-SQL statements to compute the return value here
SELECT @NC=ISNULL(@NC+',','')+Name FROM dbo.Demo WHERE Area=@Area-- Return the result of the function
RETURN @NCEND
GO
建好後測試下,以傳入參數爲「北京」爲例,運行以下代碼:
SELECT dbo.MergeByColumn('北京') AS NameCollection
獲得結果以下:
如今只需將Area列也加入查詢便可,修改代碼以下:
SELECT Area,dbo.MergeByColumn(Area) AS NameCollection From dbo.Demo
如今也獲得了重複的結果,以下:
去重複一樣能夠用GROUP BY和DISTINCT,代碼以下,便可以獲得咱們最終的結果:
SELECT DISTINCT Area,dbo.MergeByColumn(Area) AS NameCollection From dbo.Demo
SELECT Area,dbo.MergeByColumn(Area) AS NameCollection From dbo.Demo GROUP BY Area