Ses*_*ame 33 sql t-sql sql-server concatenation
我试图将一些数据汇总到一个报告中,并需要连接其中一个表的行值.这是基本的表结构:
评测
ReviewID
ReviewDate
Run Code Online (Sandbox Code Playgroud)
评审
ReviewerID
ReviewID
UserID
Run Code Online (Sandbox Code Playgroud)
用户
UserID
FName
LName
Run Code Online (Sandbox Code Playgroud)
这是M:M的关系.每个评论都可以有很多评论者; 每个用户都可以与许多评论相关联.
基本上,我想要看的是Reviews.ReviewID,Reviews.ReviewDate,以及该Review的所有相关用户的FName的串联字符串(逗号分隔).
代替:
ReviewID---ReviewDate---User
1----------12/1/2009----Bob
1----------12/1/2009----Joe
1----------12/1/2009----Frank
2----------12/9/2009----Sue
2----------12/9/2009----Alice
Run Code Online (Sandbox Code Playgroud)
显示这个:
ReviewID---ReviewDate----Users
1----------12/1/2009-----Bob, Joe, Frank
2----------12/9/2009-----Sue, Alice
Run Code Online (Sandbox Code Playgroud)
我发现这篇文章描述了一些方法,但是大多数方法似乎只处理一个表而不是多个; 不幸的是,我的SQL-fu不够强大,无法根据我的情况进行调整.我对该网站上使用FOR XML PATH()的示例特别感兴趣,因为它看起来最干净,最直接.
SELECT p1.CategoryId,
( SELECT ProductName + ', '
FROM Northwind.dbo.Products p2
WHERE p2.CategoryId = p1.CategoryId
ORDER BY ProductName FOR XML PATH('')
) AS Products
FROM Northwind.dbo.Products p1
GROUP BY CategoryId;
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮我一把吗?任何帮助将不胜感激!
Adr*_*der 33
看看这个
DECLARE @Reviews TABLE(
ReviewID INT,
ReviewDate DATETIME
)
DECLARE @Reviewers TABLE(
ReviewerID INT,
ReviewID INT,
UserID INT
)
DECLARE @Users TABLE(
UserID INT,
FName VARCHAR(50),
LName VARCHAR(50)
)
INSERT INTO @Reviews SELECT 1, '12 Jan 2009'
INSERT INTO @Reviews SELECT 2, '25 Jan 2009'
INSERT INTO @Users SELECT 1, 'Bob', ''
INSERT INTO @Users SELECT 2, 'Joe', ''
INSERT INTO @Users SELECT 3, 'Frank', ''
INSERT INTO @Users SELECT 4, 'Sue', ''
INSERT INTO @Users SELECT 5, 'Alice', ''
INSERT INTO @Reviewers SELECT 1, 1, 1
INSERT INTO @Reviewers SELECT 2, 1, 2
INSERT INTO @Reviewers SELECT 3, 1, 3
INSERT INTO @Reviewers SELECT 4, 2, 4
INSERT INTO @Reviewers SELECT 5, 2, 5
SELECT *,
(
SELECT u.FName + ','
FROM @Users u INNER JOIN
@Reviewers rs ON u.UserID = rs.UserID
WHERE rs.ReviewID = r.ReviewID
FOR XML PATH('')
) AS Products
FROM @Reviews r
Run Code Online (Sandbox Code Playgroud)
小智 20
事实证明,有一种更简单的方法可以做到这一点,不需要UDF:
select replace(replace(replace((cast((
select distinct columnName as X
from tableName
for xml path('')) as varchar(max))),
'</X><X>', ', '),'<X>', ''),'</X>','')
Run Code Online (Sandbox Code Playgroud)
小智 10
有类似的问题,并在玩代码15分钟后找到了一个甜蜜的解决方案
declare @result varchar(1000)
select @result = COALESCE(@result+','+A.col1, A.col1)
FROM ( select col1
from [table]
) A
select @result
Run Code Online (Sandbox Code Playgroud)
返回结果为value1,value2,value3,value4
请享用 ;)
正如您所描述的,有三种处理汇总数据的方法,1.使用游标,2.使用UDF或3.使用自定义聚合(用.NET CLR编写).
Cursor和UDF非常慢.(每行大约0.1秒).CLR自定义聚合速度惊人的快.(每排约0.001秒)
Microsoft提供代码(完全按照您的意愿)作为SDK for SQL 2005的一部分.如果安装了它,您应该能够在此文件夹中找到代码:C:\ Program Files\Microsoft SQL Server\90 \样本\发动机\可编程\ CLR\StringUtilities.您可能还想在MSDN中阅读本文.它讨论了如何安装自定义聚合并启用它:http: //msdn.microsoft.com/en-us/library/ms161551(SQL.90).aspx
编译并安装自定义聚合后,您应该能够像这样查询:
SELECT Reviews.ReviewID, ReviewDate, dbo.StringUtilities.Concat(FName) AS [User]
FROM Reviews INNER JOIN Reviewers ON Reviews.ReviewID = Reviewers.ReviewID
INNER JOIN Users ON Reviews.UserID = Users.UserID
GROUP BY ReviewID, ReviewDate;
Run Code Online (Sandbox Code Playgroud)
并得到一个像你所示的结果集(上图)
小智 5
select p1.Availability ,COUNT(*),
(select name+',' from AdventureWorks2008.Production.Location p2 where
p1.Availability=p2.Availability for XML path(''),type).value('.','varchar(max)')
as Name from AdventureWorks2008.Production.Location p1 group by Availability
Run Code Online (Sandbox Code Playgroud)
结果
Availability COUNT Name
---------------------------------------------------------------------------------
0.00 7 Tool Crib,Sheet Metal Racks,Paint Shop,Paint Storage,Metal
Storage,Miscellaneous Storage,Finished Goods Storage,
80.00 1 Specialized Paint,
96.00 1 Frame Forming,
108.00 1 Frame Welding,
120.00 4 Debur and Polish,Paint,Subassembly,Final Assembly,
Run Code Online (Sandbox Code Playgroud)
小智 5
现在从 SQL Server 2017 开始,有一个名为的新T-SQL函数STRING_AGG
:
它是一个新的聚合函数,用于连接字符串表达式的值并在它们之间放置分隔符值。
字符串末尾不添加分隔符。
例子:
SELECT STRING_AGG ( ISNULL(FirstName,'N/A'), ',') AS csv
FROM Person.Person;
Run Code Online (Sandbox Code Playgroud)
结果集:
John,N/A,Mike,Peter,N/A,N/A,Alice,Bob
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
49765 次 |
最近记录: |