问题描述
我有一张这样的桌子:
ID | C1 | C2 | 序列 |
---|---|---|---|
1 | 这是我的作品 | 盟友长句 | 1 |
1 | 这是我的作品 | 存储在一个 | 2 |
1 | 这是我的作品 | 非常糟糕的格式 | 3 |
而且我需要一些 sql 查询或存储过程来提取它,使其显示“这是我以非常糟糕的格式存储的非常长的句子”
select
case
when seq = '1'
then c1 else ''
end + stuff((select c2 from table t2
where t2. id = t1.id and t2.seq = t1.seq
for xml path('')),1,'')
from
table t1
我已经开始了,但它正在放入 XML,我不知道为什么。任何帮助表示赞赏。
解决方法
想通了。 for xml 并没有像我想象的那样删除 XML,只有前导字符,我不得不将 c1 强制转换为 nvarchar,导致一个未命名的列并且没有 xml :shrug:
,FOR XML
将使用列名作为节点名,所以如果你有
SELECT someCol
FROM tbl
FOR XML PATH('')
你仍然会得到这样的 XML
<someCol>someValue</someCol>
这个连接技巧的重点是获得一个未命名的列,这样就没有节点名称,只有值。所以你只需要对值使用any函数或计算来删除列名
就您而言,STUFF
不是必需的,因为您没有分隔符。
不要忘记使用 ,TYPE).value('text()[1]','nvarchar(max)')
来防止 XML 转义/实体化。
select
c1 + (
select case when 1=1 then c2 end
from table t2
where t2.id = t1.id and t2.seq >= 2
for xml path(''),type).value('text()[1]','nvarchar(max)')
from
table t1
where seq = '1';
当然,如果您使用的是 SQL Server 2017+,则可以使用 STRING_AGG
select
c1 + string_agg(cast(c2 as nvarchar(max)),'')
from
table t1
group by t1.ID,t1.c1;