【问题标题】:Querying from a XML Column across multiple rows从 XML 列跨多行查询
【发布时间】:2014-08-10 13:29:45
【问题描述】:

在 SQL Server 中,我尝试查询具有 XML 列的表,该列内的 XML 类似于下面

DECLARE @XML AS XML

SET @XML =
'<Root>
    <Stuff>
        <InsideStuff>1</InsideStuff>
        <InsideStuff>2</InsideStuff>
        <StuffIDontWant>9</StuffIDontWant>
    </Stuff>
    <Stuff>
        <InsideStuff>3</InsideStuff>
        <InsideStuff>4</InsideStuff>
        <StuffIDontWant>6</StuffIDontWant>
        <StuffIDontWant>7</StuffIDontWant>
    </Stuff>
</Root>'

SELECT TableAlias.ColumnAlias.value('(.)','nvarchar(max)') 
FROM @XML.nodes('/Root/Stuff/InsideStuff') AS TableAlias(ColumnAlias)

上面的代码会给我 1,2,3,4 这是我想要的,但是我似乎不太明白如何将它变成我想要做类似事情的连接格式

SELECT T1.Name 
FROM TableOne T1
INNER JOIN TableWithXml.ColumnWithXml.nodes('/Root/Stuff/InsideStuff') AS TableAlias(ColumnAlias) ON T1.ID = TableAlias(ColumnAlias)

在这种情况下我将如何格式化我的 T-SQL?

【问题讨论】:

  • Join on data from XML in T-SQL 的可能重复项
  • @philip-loyer 为了理解这个问题,您希望根据该列的值是否包含“InsideStuff”,将具有“InsideStuffId”的表连接到另一个具有 XML 列的表中的条目具有给定值的条目?要加入的 XML 值是否需要具有多个具有相同名称的元素(即“InsideStuff”),还是应该只有一个?我相信这会使 XQuery 更容易。
  • 在我的场景中,一个表的列具有一个整数值,我想将其连接到另一个表中的 xml 列上,该表在 xml 中有 4 个匹配的整数。我希望能够知道 xml 和另一个表中的整数是什么

标签: sql sql-server xml tsql


【解决方案1】:

主要目标是将 XML 展平到所需的级别,形成可以在查询中使用的表。

假定的表结构:

DECLARE @TableWithXml TABLE (
    ID int IDENTITY(1,1),
    XmlCol XML
);

DECLARE @TableOne TABLE (
    ID int IDENTITY(1,1),
    StuffId int
);

解决方案 1:如果您不关心除 xml 是否包含给定值之外的任何其他数据,只需将其展平一层并检查值:(sqlfiddle):

SELECT t1.ID as T1ID, t2.ID as TXID, t2.XmlCol
FROM @TableOne t1
CROSS JOIN @TableWithXml t2
WHERE t1.StuffId IN (
    SELECT      XmlData.InsideStuff.value('(.)','int') as InsideStuff
    FROM        @TableWithXml tX
    CROSS APPLY tX.XmlCol.nodes('/Root/Stuff/InsideStuff') as XmlData(InsideStuff)
    WHERE       tX.ID = t2.ID
);

-- // Or alternatively...

SELECT      t1.ID as T1ID, FlattenedTable.TXID, FlattenedTable.InsideStuff, FlattenedTable.XmlCol
FROM        @TableOne t1
INNER JOIN  (
    SELECT      tx.ID as TXID, tx.XmlCol, XmlData.InsideStuff.value('(.)','int') as InsideStuff
    FROM        @TableWithXml tX
    CROSS APPLY tX.XmlCol.nodes('/Root/Stuff/InsideStuff') as XmlData(InsideStuff)
) as FlattenedTable ON t1.StuffId = FlattenedTable.InsideStuff

解决方案 2:如果您想使用 XML 数据,请将其完全展平 (sqlfiddle):

SELECT      t1.ID as T1ID,
            tx.ID as TXID, 
            Stuffs_InsideStuff.val.value('(.)', 'int') as InsideStuffId, 
            Stuffs_StuffIDontWant.val.value('(.)', 'nvarchar(max)') as StuffIDontWant
FROM        @TableOne t1
INNER JOIN  (
    @TableWithXml tX
    CROSS APPLY tX.xmlCol.nodes('/Root/Stuff') as XmlData(Stuffs)
    CROSS APPLY XmlData.Stuffs.nodes('InsideStuff') as Stuffs_InsideStuff(val)
    CROSS APPLY XmlData.Stuffs.nodes('StuffIDontWant') as Stuffs_StuffIDontWant(val)
) on t1.stuffId = Stuffs_InsideStuff.val.value('(.)', 'int');

【讨论】:

  • 谢谢!你帮助我在 SQL 中了解了比我真正想知道的更多的 XML :)
猜你喜欢
  • 1970-01-01
  • 2017-01-30
  • 2023-04-06
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多