我的sql数据库中有三个表,我正尝试使用3个表中的填充函数折叠sql server中的行
我尝试进行内部联接,但尝试进行外部联接,但未获得预期的结果 我的代码在下面:
select T1.Id,
T1.Name,
T2.Id,
T2.T1_Id,
T2.Name,
stuff(
(
select ','+T3.Name
from Test3 T3
where T3.Id=T2.T3_Id for xml path('')
),1,1,'') as Test5
from Test1 T1,Test2 T2
where T1.Id=T2.T1_Id
我得到了类似的结果
Id Name Id T1_Id Name Test5
----------------------------------------------
1 Test1 1 1 ASD BAAN
1 Test1 2 1 ASD KAAL
预期
Id Name Id T1_Id Name Test5
1 Test1 1 1 ASD BAAN,KAAL
我的表脚本和示例数据是,我正在使用sql server 2014
CREATE TABLE [dbo].[Test1](
[Id] [int] NULL,
[Name] [varchar](50) NULL
) ON [PRIMARY]
GO
INSERT INTO [dbo].[Test1]
([Id]
,[Name])
VALUES
(1
,'Test1')
GO
CREATE TABLE [dbo].[Test2](
[Id] [int] NOT NULL,
[T1_Id] [int] NOT NULL,
[T3_Id] [int] NOT NULL,
[Name] [varchar](50) NULL
) ON [PRIMARY]
INSERT INTO [dbo].[Test2]
([Id]
,[T1_Id]
,[T3_Id]
,[Name])
VALUES
(1
,1
,1
,'ASD'),(2,1,2,'ASD')
GO
CREATE TABLE [dbo].[Test3](
[Id] [int] NULL,
[Name] [varchar](50) NULL
) ON [PRIMARY]
GO
INSERT INTO [dbo].[Test3]
([Id]
,[Name])
VALUES
(1
,'KAAL'),(2,'BAAL')
Go
答案 0 :(得分:2)
SQL语言中没有“ COLLAPSE”。您发布的内容将显示分组和汇总。对于字符串,唯一有意义的聚合是MIN,MAX和字符串串联。
SQL Server 2017通过STRING_AGG
函数提供字符串连接。其他数据库产品使用不同的名称,例如GROUP_CONCAT
。在早期的SQL Server版本中,使用了各种技术来执行相同的操作。您发布的是XML技术。
查询中没有GROUP BY子句,这就是为什么返回多行的原因。
在SQL Server 2017中,查询将如下所示:
select T1.Id,
T1.Name,
MIN(T2.Id) as T2_ID,
MIN(T2.T1_Id) as T1_ID,
MIN(T2.Name) as T2_Name,
STRING_AGG(T3.Name,', ') as Test5
from @Test1 T1
inner join @Test2 T2 on T1.Id=T2.T1_Id
inner join @Test3 T3 on T3.Id=T2.T3_Id
GROUP BY T1.ID,T1.Name
在早期版本中执行相同操作比较麻烦。 FOR XML
查询只能与GROUP BY子句中出现的列相关:
select T1.Id,
T1.Name,
MIN(T2.Id),
MIN(T2.T1_Id),
MIN(T2.Name),
stuff(
(
SELECT ','+T3.Name
FROM @Test3 T3
inner join @Test2 TT2 on T3.Id=TT2.T3_Id
WHERE TT2.T1_ID=T1.Id
FOR XML PATH('')
),1,1,'') as Test5
from @Test1 T1
inner join @Test2 T2 on T1.Id=T2.T1_Id
GROUP BY T1.ID,T1.Name
将整个STUFF(... FOR XML)..
部分作为单个函数考虑,该函数以WHERE
子句中分组列之一作为参数,搜索一些表并连接字符串结果。
这意味着相关子句
WHERE TT2.T1_ID=T1.Id
只能引用外部查询中的分组列。我们需要在那里加入T2,因为我们无法直接从T3进入T1.ID
如果您不关心T2列,则可以摆脱外部查询中的JOIN:
select T1.Id,
T1.Name,
stuff(
(
select ','+T3.Name
from @Test3 T3
inner join @Test2 TT2 on T3.Id=TT2.T3_Id
where TT2.T1_ID=T1.Id for xml path('')
),1,1,'') as Test5
from @Test1 T1
GROUP BY T1.ID,T1.Name
答案 1 :(得分:1)
尝试一下
;WITH CTE AS
(
SELECT T1.Id AS T1_Id,
T1.Name AS T1_Name,
T2.Id AS T2_Id,
T2.T1_Id AS T2_T1_Id,
T2.Name AS T2_Name,
T3.Name AS Test5
FROM [Test2] t2
INNER JOIN [Test1] t1
ON t1.Id = t2.T1_Id
INNER JOIN [Test3] t3
ON t3.id = t2.T3_Id
)
SELECT T1_Id,
T1_Name,
T2_T1_Id,
T2_Name,
STUFF((SELECT ', '+Test5
FROM CTE i WHERE i.T1_Id = o.T1_Id
FOR XML PATH ('')),1,1,'') AS Test5
FROM CTE o
GROUP BY T1_Id,
T1_Name,
T2_T1_Id,
T2_Name
答案 2 :(得分:1)
如果您不关心Test2.Name,则可以得到如下结果:
WITH tblMain as (SELECT T1.Id,T1.Name, T3.Name T3Name
FROM Test2 T2 LEFT OUTER JOIN
Test1 T1 on T2.T1_Id = T1.Id LEFT OUTER JOIN
Test3 T3 on T2.T3_Id = T3.Id)
SELECT Id, Name,
STUFF((SELECT ', ' + T3Name
FROM tblMain b
WHERE b.Id = a.Id AND b.Name = a.Name
FOR XML PATH('')), 1, 2, '') as Test5
FROM tblMain a
GROUP BY Id, Name
否则,如果要从Test2中获取其他列,也应将它们添加到GROUP BY
子句中。
答案 3 :(得分:0)
尝试以下脚本。
注意:您必须避免从Test2和Test3获得ID,否则您不能为STUFF应用GROUP BY,因为它们在ID列中具有不同的值。
SELECT *,
STUFF
(
(
SELECT ',' + Name
FROM
(
SELECT T3.Name
FROM Test1 T1
INNER JOIN Test2 T2 ON T1.Id = T2.T1_Id
INNER JOIN Test3 T3 ON T2.T3_Id = T3.ID
) B
FOR XML PATH ('')
), 1, 1, ''
) Test5
FROM
(
SELECT T1.Id,T1.Name T1_Name,T2.Name T2_Name
FROM Test1 T1
INNER JOIN Test2 T2 ON T1.Id = T2.T1_Id
)A
GROUP BY A.Id,A.T1_Name,A.T2_Name