繁体   English   中英

如何在SQL Server中将多行连接成一列?

[英]How do you concat multiple rows into one column in SQL Server?

我已经高低搜索了这个答案,但我无法弄明白。 我对SQL Server比较陌生,但还没有很好的语法。 我有这个数据结构(简化):

Table "Users"         | Table "Tags":
UserID    UserName    | TagID    UserID    PhotoID
1         Bob         | 1        1         1
2         Bill        | 2        2         1
3         Jane        | 3        3         1
4         Sam         | 4        2         2
-----------------------------------------------------
Table "Photos":              | Table "Albums":
PhotoID   UserID    AlbumID  | AlbumID     UserID
1         1         1        | 1           1
2         1         1        | 2           3
3         1         1        | 3           2
4         3         2        |
5         3         2        |

我正在寻找一种方法来获取所有照片信息(简单)以及该照片的所有标签连接如CONCAT(username, ', ') AS Tags当然删除了最后一个逗号。 我有一段时间试图这样做。 我已经尝试了本文中的方法,但是当我尝试运行查询说我无法使用DECLARE语句时出现错误...你们有任何想法如何做到这一点? 我正在使用VS08和其中安装的任何数据库(我通常使用MySQL,所以我不知道这是什么类型的DB真的是......它是一个.mdf文件?)

好吧,我觉得我需要深入评论如何在SQL Server中将多行连接成一列? 并提供更优选的答案。

我很抱歉,但使用这样的标量值函数会破坏性能。 只需打开SQL事件探查器,看看当你使用调用表的标量函数时会发生什么。

此外,不鼓励使用“更新变量”技术进行连接,因为该功能可能在将来的版本中不会继续。

执行字符串连接以使用FOR XML PATH的首选方法。

select
 stuff((select ', ' + t.tag from tags t where t.photoid = p.photoid order by tag for xml path('')),1,2,'') as taglist
 ,*
from photos
order by photoid;

有关FOR XML PATH如何工作的示例,请考虑以下内容,假设您有一个包含两个名为“id”和“name”的字段的表

SELECT id, name
FROM table
order by name
FOR XML PATH('item'),root('itemlist')
;

得到:

<itemlist><item><id>2</id><name>Aardvark</a></item><item><id>1</id><name>Zebra</name></item></itemlist>

但如果你忽略ROOT,你会得到一些略有不同的东西:

SELECT id, name
FROM table
order by name
FOR XML PATH('item')
;

<item><id>2</id><name>Aardvark</a></item><item><id>1</id><name>Zebra</name></item>

如果你输入一个空的PATH字符串,你会更接近普通的字符串连接:

SELECT id, name
FROM table
order by name
FOR XML PATH('')
;

<id>2</id><name>Aardvark</a><id>1</id><name>Zebra</name>

现在来了一个非常棘手的问题......如果你命名一个以@符号开头的列,它就会成为一个属性,如果一个列没有名字(或者你称之为[*]),那么它就会遗漏标签也是:

SELECT ',' + name
FROM table
order by name
FOR XML PATH('')
;

,Aardvark,Zebra

最后,为了去除前导逗号,STUFF命令进入.STUFF(s,x,n,s2)从位置x开始抽出s的n个字符。 取而代之的是s2。 所以:

SELECT STUFF('abcde',2,3,'123456');

得到:

a123456e

现在看看我上面的标记列表查询。

select
 stuff((select ', ' + t.tag from tags t where t.photoid = p.photoid order by tag for xml path('')),1,2,'') as taglist
 ,*
from photos
order by photoid;

对于每张照片,我都有一个子查询,它抓取标签并将它们(按顺序)与一个commma和一个空格连接起来。 然后我在一个stuff命令中包围该子查询以去除前导逗号和空格。

我为任何打字错误道歉 - 我实际上并没有在我自己的机器上创建表来测试它。

我要创建一个UDF:

create function GetTags(PhotoID int) returns @tags varchar(max)
as
begin
    declare @mytags varchar(max)
    set @mytags = ''

    select @mytags = @mytags + ', ' + tag from tags where photoid = @photoid

    return substring(@mytags, 3, 8000)
end

然后,您所要做的就是:

select GetTags(photoID) as tagList from photos
Street_Name   ; Street_Code

  1. 西 | 14
  2. | 7
  3. 西+东| 714

如果要显示两个不同的行连续本身,怎么办呢? (我的意思是我想从选择结果显示的最后一行。我的表有第一和第二条记录)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM