MS SQL Server 中的组连接
Posted
技术标签:
【中文标题】MS SQL Server 中的组连接【英文标题】:Group Concatenate in MS SQL Server 【发布时间】:2014-03-13 16:58:07 【问题描述】:我有两个表 dbo.Supplier 和 dbo.L_ProductSupplier (AS LPST),对于 LPST 表上的所有产品 ID,我想连接 dbo.Supplier (AS ST) 中的供应商名称,该供应商名称通过 SupplierID 链接到 LPST字段(每个产品可以有多个供应商)
例如查询应该这样:
LPST.ProductID LPST.SupplierID ST.SupplierName
1 A CompanyA
1 B CompanyB
1 C CompanyC
2 X CompanyX
2 Y CompanyY
2 Z CompanyZ
然后输出:
LPST.ProductID SupplierName(s)
1 CompanyA / CompanyB /CompanyC
2 CompanyX / CompanyY / CompanyZ
我尝试了以下代码:
SELECT DISTINCT
LPST.ProductId,
STUFF((SELECT ',' + ST.SupplierName
FROM dbo.Supplier AS ST
WHERE LPST.SupplierId=ST.SupplierId
FOR XML PATH('')),1,1,'') AS SupplierNames
FROM dbo.L_ProductSupplier AS LPST
GROUP BY LPST.ProductId
...但它给出了错误:列 'dbo.L_ProductSupplier.SupplierId' 在选择列表中无效,因为它既不包含在聚合函数或 GROUP BY 子句中。关于如何解决这个问题的任何想法?如果我删除“分组依据”,那么它会在没有串联的情况下报告 LPST 上的每一行。
还有其他方法吗?我听说游标是一种选择,但我是 SQL 新手,不熟悉它们;有人在这种情况下使用过游标吗?
【问题讨论】:
有几种方法可以做到这一点——没有一种特别优雅。有关您的选项的完整列表,请参阅link。我可能会选择FOR XML PATH
选项(根据 KumarHarsh 的回答),因为它最简洁
谢谢詹姆斯,FOR XML PATH 是我走的路线,但我的代码没有达到预期的结果,有什么想法我出错了吗?
【参考方案1】:
怎么样
DECLARE @Supplier TABLE(
SupplierId INT,
SupplierName VARCHAR(50)
)
INSERT INTO @Supplier SELECT 1, 'A'
INSERT INTO @Supplier SELECT 2, 'B'
DECLARE @L_ProductSupplier TABLE(
ProductId INT,
SupplierId INT
)
INSERT INTO @L_ProductSupplier SELECT 1, 1
INSERT INTO @L_ProductSupplier SELECT 1, 2
;WITH Vals AS (
SELECT LPST.ProductId,
LPST.SupplierId,
ST.SupplierName
FROM @L_ProductSupplier LPST LEFT JOIN
@Supplier ST ON LPST.SupplierId = st.SupplierId
)
SELECT LPST.ProductId,
STUFF(
(
SELECT ',' + ST.SupplierName
FROM Vals AS ST
WHERE LPST.ProductId=ST.ProductId
FOR XML PATH('')
),
1,
1,
''
) AS SupplierNames
FROM Vals AS LPST
GROUP BY LPST.ProductId
SQL Fiddle DEMO
【讨论】:
感谢 asstander,如果有 200 个公司名称并且我不知道哪些对应于哪些产品,这会起作用吗?【参考方案2】:Declare @t table (ProductID int, SupplierID varchar(1),SupplierName varchar(50))
insert into @t
select 1 , 'A' , 'CompanyA' union all
select 1 , 'B' , 'CompanyB' union all
select 1 , 'C' , 'CompanyC' union all
select 2 , 'X' , 'CompanyX' union all
select 2 , 'Y' , 'CompanyY' union all
select 2 , 'Z' , 'CompanyZ'
select distinct b.ProductID,stuff((select '/'+a.SupplierName from @t a where a.ProductID=b.ProductID FOR XML path('')),1,1,'')
from @t b
【讨论】:
谢谢 KumarHarsh... ABCXYZ 只是为了演示,如果有 200 个公司名称,我不知道它们是什么? @user3309874,只要你想根据productid连接供应商名称,你必须提供真实的场景数据。200公司名称无关紧要。告诉我它赢得了哪些样本数据不工作以上是关于MS SQL Server 中的组连接的主要内容,如果未能解决你的问题,请参考以下文章
linux系统可以使用哪些.so文件对应windows中的.dll文件来连接php到ms sql server
为啥 MS-Access 中的 Teradata 查询比 SQL Server 更快