很有意思的SQL多行数据拼接 转

 

 

要实现的SQL查询很原始:

要求从第一个表进行查询得到第二个表格式的数据,上网查询之后竟然能写出下面的SQL:

复制代码代码如下:

select * from userino 

SELECT * FROM( 
SELECT DISTINCT userpart 
FROM userino 
)A 
OUTER APPLY( 
SELECT 
[usernames]= replace(replace(replace((SELECT username as value FROM userino N 
WHERE userpart = A.userpart order by n.username asc FOR XML AUTO),'"/><N value="','/') 
,'<N value="',''),'"/>','') 
)N 
OUTER APPLY( 
SELECT 
[username_cns]= replace(replace(replace((SELECT username_cn as value FROM userino M 
WHERE userpart = A.userpart order by m.username asc FOR XML AUTO),'"/><M value="','/') 
,'<M value="',''),'"/>','') 

)M 

现将SQL进行一下分析: 

总共使用到的点有:OUTER APPLY,FOR XML AUTO。由于对SQL Server没有很深的研究,所以记录一下 

OUTER APPLY 是SQL2005开始支持的一种查询方法,类似于连接查询,是将两个查询结果进行拼接,但是奇特的是,使用OUTER APPLY竟然能够在Apply后面的查询中使用前面已经得到的查询结果。 

如: 
复制代码代码如下:

select * from 
(select * from userino) A 
cross join (select username from userino 
where username = A.username )B 

select * from 
(select * from userino) A 
join (select username from userino ) B on a.username = b.username 

select * from 
(select * from userino) A 
OUTER APPLY (select username from userino 
where username = A.username ) B 

第一段SQL显然是错的,有两个原因:1.Cross Join本来就是无条件的,2. SQl Server会爆出如下错误: 

The multi-part identifier "A.username" could not be bound. 

大家可能会说有条件的Join查询本来就不是这样写的,应该写为第二条SQL这样的样子,其实这样写和第三条SQL中使用Outer apply 实现的效果是一样的 

可是 Outer Apply还能实现如下的效果 
复制代码代码如下:

select * from 
(select * from userino) A 
OUTER APPLY (select [value] = a.username+'test' ) B 

这个恐怕直接使用join就有点麻烦了,上面的例子也许没什么意义,其实SQL2005提出Apply连接方法主要是为了在连接查询中使用已经执行的查询语句的结果 

除了“OUTER APPLY”,SQL Server还有CROSS APPLY,之间的区别主要是在Null值的处理上 

FOR XML AUTO 主要用于将SQL的查询结果直接返回成XML语句,For Xml 除了auto外 还有RAW和EXPLICIT,详见《超级简单:使用FOR XML AUTO控制XML输出》 

在文章刚开始提出的SQL文,就是使用了上面的两个特性,首先使用Outer Apply来实现类似于使用userpart进行分组的效果,来分别筛选出各个userpart中的user,然后由于筛选出的结果是多行,所以使用 for xml 来把多行数据拼接成xml,最后很二的对xml进行拆分

 

SQL Server 中,可以使用 FOR XML PATH() 语句来实现多行拼接。具体步骤如下: 1. 使用 SELECT 语句查询需要拼接数据,并使用 FOR XML PATH() 语句将每行数据换为 XML 格式。 2. 在 FOR XML PATH() 语句中指定一个标签名称,该标签将用于将每行数据包装在其中。 3. 使用 STUFF() 函数将每行数据连接在一起,并使用指定的分隔符分隔每行数据。 下面是一个示例: 假设有一个名为 Students 的表,其中包含以下数据: | ID | Name | Age | |----|--------|-----| | 1 | Alice | 20 | | 2 | Bob | 22 | | 3 | Charlie| 21 | 现在需要将所有学生的姓名连接在一起,以逗号分隔。可以使用以下 SQL 语句: ``` SELECT STUFF((SELECT ', ' + Name FROM Students FOR XML PATH('')), 1, 2, '') AS Names ``` 该语句将返回以下结果: | Names | |-----------------------| | Alice, Bob, Charlie | 解释: 1. SELECT ', ' + Name FROM Students FOR XML PATH('') 将每行数据换为 XML 格式,并使用逗号分隔每行数据。 2. FOR XML PATH('') 指定一个空标签名称,将每行数据包装在其中。 3. STUFF() 函数将每行数据连接在一起,并使用指定的分隔符分隔每行数据。第一个参数是要修改的字符串,第二个参数是要替换的起始位置,第三个参数是要替换的字符数,第四个参数是要插入的新字符串。在这个例子中,我们将从第一个字符开始替换两个字符(即第一个逗号和空格),并将它们替换为一个空字符串。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值