具有多个字段的 XML 路径的 SQL 东西

Posted

技术标签:

【中文标题】具有多个字段的 XML 路径的 SQL 东西【英文标题】:SQL Stuff For XML Path with Multiple Fields 【发布时间】:2017-05-04 18:32:47 【问题描述】:

我正在使用 SQL Server 2008。我正在尝试使用 STUFF 和 FOR XML PATH 编写一个选择语句,以便在一个字段中创建一个逗号分隔的字符串。只有一条记录,但有31个字段。

我正在从 1 个表中提取数据,该表在该月的每一天都有一个 smallint 字段 - 0 表示当天没有,1 表示是。 (这张桌子不是我设计的,很遗憾我不能改变它。)像这样:

z1st   z2nd   z3rd   z4th   z5th   z6th   z7th   z8th   z9th   z10th
------ ------ ------ ------ ------ ------ ------ ------ ------ ------
0      1      0      0      0      0      0      0      0      0
0      0      0      0      1      0      0      0      0      1
0      0      1      0      0      0      0      0      0      0
0      0      0      1      0      0      0      0      0      0
0      1      0      0      0      0      0      0      0      1

以此类推,一直到 z31st。

我的语句正在传递整数变量@order_snbr 和@admin_nbr,它们将始终返回一行。

DECLARE @strSelectedDayList AS VARCHAR(MAX)

SELECT @strSelectedDayList = STUFF((SELECT ', ' + CASE WHEN td1.z1st = 1 THEN '1st' END
, CASE WHEN td1.z2nd = 1 THEN '2nd' END
, CASE WHEN td1.z3rd = 1 THEN '3rd' END
, CASE WHEN td1.z4th = 1 THEN '4th' END
, CASE WHEN td1.z5th = 1 THEN '5th' END
, CASE WHEN td1.z6th = 1 THEN '6th' END
, CASE WHEN td1.z7th = 1 THEN '7th' END
, CASE WHEN td1.z8th = 1 THEN '8th' END
, CASE WHEN td1.z9th = 1 THEN '9th' END
, CASE WHEN td1.z10th = 1 THEN '10th' END
, CASE WHEN td1.z11th = 1 THEN '11th' END
, CASE WHEN td1.z12th = 1 THEN '12th' END
, CASE WHEN td1.z13th = 1 THEN '13th' END
, CASE WHEN td1.z14th = 1 THEN '14th' END
, CASE WHEN td1.z15th = 1 THEN '15th' END
, CASE WHEN td1.z16th = 1 THEN '16th' END
, CASE WHEN td1.z17th = 1 THEN '17th' END
, CASE WHEN td1.z18th = 1 THEN '18th' END
, CASE WHEN td1.z19th = 1 THEN '19th' END
, CASE WHEN td1.z20th = 1 THEN '20th' END
, CASE WHEN td1.z21st = 1 THEN '21st' END
, CASE WHEN td1.z22nd = 1 THEN '22nd' END
, CASE WHEN td1.z23rd = 1 THEN '23rd' END
, CASE WHEN td1.z24th = 1 THEN '24th' END
, CASE WHEN td1.z25th = 1 THEN '25th' END
, CASE WHEN td1.z26th = 1 THEN '26th' END
, CASE WHEN td1.z27th = 1 THEN '27th' END
, CASE WHEN td1.z28th = 1 THEN '28th' END
, CASE WHEN td1.z29th = 1 THEN '29th' END
, CASE WHEN td1.z30th = 1 THEN '30th' END
, CASE WHEN td1.z31st = 1 THEN '31st' END
FROM TableDays td1 WITH(NOLOCK) 
WHERE td1.order_snbr = td2.order_snbr 
AND td1.admin_nbr = td2.admin_nbr 
FOR XML PATH('')), 1, 1, '')
FROM TableDays td2 WITH(NOLOCK)
WHERE td2.order_snbr = @order_snbr
AND td2.admin_nbr = @admin_nbr

PRINT @strSelectedDayList

这会产生如下结果:

1st14th28th

我想要的是这样的:

1st, 14th, 28th

任何帮助将不胜感激!如果有更好的方法来做到这一点(没有 STUFF 或 FOR XML PATH),我很乐意切换。

【问题讨论】:

【参考方案1】:

也许是另一种方法

示例

Declare @YourTable Table ([z1st] varchar(50),[z2nd] varchar(50),[z3rd] varchar(50),[z4th] varchar(50),[z5th] varchar(50),[z6th] varchar(50),[z7th] varchar(50),[z8th] varchar(50),[z9th] varchar(50))
Insert Into @YourTable Values
 (0,1,0,0,0,1,0,0,0)
,(0,0,0,0,1,0,0,1,0)
,(0,0,1,0,0,0,0,0,0)
,(1,1,1,1,0,0,0,0,0)
,(0,1,0,0,0,0,1,0,1)

Select A.*
      ,C.* 
 From  @YourTable A
 Cross Apply (Select XMLData = cast((select A.* for XML Raw) as xml) ) B
 Cross Apply (
                Select S = Stuff((Select ', ' +replace(Item,'z','')
                 From (
                        Select Item   = attr.value('local-name(.)','varchar(100)')
                         From  B.XMLData.nodes('/row') as A(r)
                         Cross Apply A.r.nodes('./@*') AS B(attr)
                         Where attr.value('local-name(.)','varchar(100)') like 'z[0-9]%'
                           and attr.value('.','varchar(max)') =1
                      ) C1
                 For XML Path ('')),1,2,'') 
             ) C

退货

【讨论】:

这真是太聪明了! @n8wrl 嘘……别告诉我妻子。她会希望我做事。 @MFLuder 很高兴它有帮助

以上是关于具有多个字段的 XML 路径的 SQL 东西的主要内容,如果未能解决你的问题,请参考以下文章

将 XML 数据插入到具有多个节点的 SQL 表中

SQL 查找具有多个字段的重复项(没有唯一 ID)

SQL:当1个字段具有多个类别时如何设计数据库?

自动创建具有多列的 SQL 表

选择那些具有多个条目的字段[重复]

使用具有多个条件的 XMLNode(.Net) 获取 XML 节点