如何解决从 SQL 服务器中的行连接
我想从多行连接
表格:
|id |Attribute |Value | |--------|------------|---------| |101 |Manager |Rudolf | |101 |Account |456 | |101 |Code |B | |102 |Manager |Anna | |102 |Cardno |123 | |102 |Code |B | |102 |Code |C |
我正在寻找的结果是:
|id |Manager|Account|Cardno|Code | |--------|-------|-------|------|----------| |101 |Rudolf |456 | |B | |102 |Anna | |123 |B,C |
我有以下来自 related question 的代码:
select
p.*,a.value as Manager,b.value as Account,c.value as Cardno
from table1 p
left join table2 a on a.id = p.id and a.attribute = 'Manager'
left join table2 b on b.id = p.id and b.attribute = 'Account'
left join table2 c on c.id = p.id and b.attribute = 'Cardno'
但是,它对于 ID# 102 的 Code
属性失败,其中 B
和 C
值都存在。
如何更新它以在同一结果中包含这两个值?
解决方法
UPD:“STRING_AGG 仅适用于 Server 2017+” 您可以使用 CTE 和 STRING_AGG 函数解决此任务,例如:
declare
@t table (id int,Attribute varchar (100),[Value] varchar (100) )
insert into @t
values
(101,'Manager','Rudolf'),(101,'Account','456'),'Code','B'),(102,'Anna'),'Cardno','123'),'C')
;with cte as
(
select id,Attribute,STRING_AGG([Value],',') WITHIN GROUP (ORDER BY ID ASC) AS [Value]
from @t
group by ID,Attribute
)
select
max(p.ID) ID,a.Value Manager,isnull(b.Value,'') Account,isnull(c.Value,'') Cardno,isnull(e.Value,'') Code
from cte p
left join cte a on a.id =p.ID and a.attribute = 'Manager'
left join cte b on b.id = p.id and b.attribute = 'Account'
left join cte c on c.id = p.id and c.attribute = 'Cardno'
left join cte e on e.id = p.id and e.attribute = 'Code'
group by p.ID,a.Value,b.Value,c.Value,e.Value
,
另一种通过 XML 和 XQuery 的方法。
它适用于 SQL Server 2008 及更高版本。
SQL
-- DDL and sample data population,start
DECLARE @tbl TABLE (ID INT,attribute VARCHAR(20),[Value] VARCHAR(30));
INSERT INTO @tbl (ID,attribute,Value) VALUES
(101,'C');
-- DDL and sample data population,end
;WITH rs AS
(
SELECT ID,(
SELECT *
FROM @tbl AS c
WHERE c.id = p.id
FOR XML PATH('r'),TYPE,ROOT('root')
) AS xmldata
FROM @tbl AS p
GROUP BY id
)
SELECT ID,COALESCE(xmldata.value('(/root/r[attribute="Manager"]/Value/text())[1]','VARCHAR(30)'),'') AS Manager,COALESCE(xmldata.value('(/root/r[attribute="Account"]/Value/text())[1]','') AS Account,COALESCE(xmldata.value('(/root/r[attribute="Cardno"]/Value/text())[1]','') AS Cardno,COALESCE(REPLACE(xmldata.query('data(/root/r[attribute="Code"]/Value)').value('.','VARCHAR(MAX)'),SPACE(1),'),'') AS Code
FROM rs
ORDER BY ID;
输出
+-----+---------+---------+--------+------+
| ID | Manager | Account | Cardno | Code |
+-----+---------+---------+--------+------+
| 101 | Rudolf | 456 | | B |
| 102 | Anna | | 123 | B,C |
+-----+---------+---------+--------+------+
,
如果您使用的是 SQL SERVER 2017 或更高版本,那么 string_agg()
和 PIVOT()
将易于使用,但性能解决方案 (Query#1
) 的速度要快得多。
如果您使用的是较旧版本的 SQL Server,则使用 Query#2
和 STUFF()
将值与 XML PATH FOR()
一起使用
架构:
PIVOT()
使用 STRING_AGG() 查询#1 PIVOT():
create table table1 (id int,Attribute varchar(50),Value varchar(50));
insert into table1 values(101,'Rudolf');
insert into table1 values(101,'456');
insert into table1 values(101,'B');
insert into table1 values(102,'Anna');
insert into table1 values(102,'123');
insert into table1 values(102,'C');
GO
输出:
id | manager | 帐号 | cardno | 代码 |
---|---|---|---|---|
101 | 鲁道夫 | 456 | B |
|
102 | 安娜 | 123 |
B,C |
|
Query#2 PIVOT() WITH STUFF() 和 XML PATH FOR():
select *
from
(
select t1.id,t1.attribute,string_agg(value,') AS value
from table1 t1
group by t1.id,t1.attribute
) d
pivot
(
max(value)
for attribute in (manager,account,cardno,code)
) piv
输出:
id | manager | 帐号 | cardno | 代码 |
---|---|---|---|---|
101 | 鲁道夫 | 456 | B |
|
102 | 安娜 | 123 |
B,C |
|
db
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。