【问题标题】:OPENXML does not return the expected resultOPENXML 未返回预期结果
【发布时间】:2016-05-27 11:24:58
【问题描述】:

我有一个 XML

<response>
  <message_infos>
    <message_info>
      <id>397300589</id>
      <pdu_id>673399673</pdu_id>
      <status>12</status>
      <id>397300589</id>
      <pdu_id>673399675</pdu_id>
      <status>12</status>
    </message_info>
    <message_info>
      <id>397300591</id>
      <pdu_id>673399669</pdu_id>
      <status>12</status>
      <id>397300591</id>
      <pdu_id>673399671</pdu_id>
      <status>12</status>
    </message_info>
  </message_infos>
</response>

我需要另存为

397300589   673399673   12
397300589   673399675   12
397300591   673399669   12
397300591   673399671   12

但是

SELECT *
FROM OPENXML(@ixml, '/response/message_infos/message_info')
WITH (id VARCHAR(50) 'id', pdu_id VARCHAR(50) 'pdu_id', status INT 'status')

给我错误的结果:

397300589   673399673   12
397300591   673399669   12

我做错了什么?我没有找到相同的例子,有人可以帮助我吗?

【问题讨论】:

  • 嗨,R.Gravis,我刚刚发布了一个性能比较的答案...

标签: sql-server xml tsql xquery openxml


【解决方案1】:
DECLARE @xml XML = N'
<response>
  <message_infos>
    <message_info>
      <id>397300589</id>
      <pdu_id>673399673</pdu_id>
      <status>12</status>
      <id>397300589</id>
      <pdu_id>673399675</pdu_id>
      <status>12</status>
    </message_info>
    <message_info>
      <id>397300591</id>
      <pdu_id>673399669</pdu_id>
      <status>12</status>
      <id>397300591</id>
      <pdu_id>673399671</pdu_id>
      <status>12</status>
    </message_info>
  </message_infos>
</response>'

SELECT
      id = MIN(CASE WHEN RowNumGroup = 1 THEN val END)
    , pdu_id = MIN(CASE WHEN RowNumGroup = 2 THEN val END)
    , [status] = MIN(CASE WHEN RowNumGroup = 0 THEN val END)
FROM (
    SELECT
          val = t.c.value('(./text())[1]', 'BIGINT')
        , RowNum = ROW_NUMBER() OVER (ORDER BY 1/0)
        , RowNumGroup = ROW_NUMBER() OVER (ORDER BY 1/0) % 3
    FROM @xml.nodes('/response/message_infos/message_info/*') t(c)
) t
GROUP BY RowNum - CASE WHEN RowNumGroup = 0 THEN 3 ELSE RowNumGroup END

2016 年 5 月 30 日更新

准备数据:

SET NOCOUNT ON
IF OBJECT_ID('tempdb.dbo.#xml') IS NOT NULL
    DROP TABLE #xml
GO
CREATE TABLE #xml (data XML)
GO
INSERT INTO #xml
SELECT TOP(10000) N'
<response>
  <message_infos>
    <message_info>
      <id>397300589</id>
      <pdu_id>673399673</pdu_id>
      <status>12</status>
      <id>397300589</id>
      <pdu_id>673399675</pdu_id>
      <status>12</status>
    </message_info>
    <message_info>
      <id>397300591</id>
      <pdu_id>673399669</pdu_id>
      <status>12</status>
      <id>397300591</id>
      <pdu_id>673399671</pdu_id>
      <status>12</status>
    </message_info>
  </message_infos>
</response>'
FROM [master].dbo.spt_values

米凯尔·埃里克森

DECLARE @d DATETIME = GETDATE()

SELECT T.X.value('(id/text())[sql:column("N.N")][1]', 'INT') AS id,
       T.X.value('(pdu_id/text())[sql:column("N.N")][1]', 'INT') AS pdu_id,
       T.X.value('(status/text())[sql:column("N.N")][1]', 'INT') AS [status]
FROM #xml x
CROSS APPLY data.nodes('/response/message_infos/message_info') AS T(X)
CROSS APPLY (
    VALUES
        (1),(2),(3),(4),(5),
        (6),(7),(8),(9),(10)
) AS N(N)
WHERE N.N <= T.X.value('count(id)', 'INT')

SELECT 'Mikael Eriksson: ' +  CAST(CAST(GETDATE() - @d AS TIME) AS VARCHAR(100))
GO

Shnugo

DECLARE @d DATETIME = GETDATE()

WITH AllMessageInfos AS (
    SELECT ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) AS Mi_Index
         , mi.query('.') AS TheMI
    FROM #xml x
    CROSS APPLY data.nodes('/response/message_infos/message_info') AS A(mi)
)
, AllIDs AS (
    SELECT Mi_Index
         , ROW_NUMBER() OVER(PARTITION BY Mi_Index ORDER BY (SELECT NULL)) AS id_Index
         , id.value('.','NVARCHAR(MAX)') AS id
    FROM AllMessageInfos
    CROSS APPLY TheMI.nodes('message_info/id') AS a(id)   
)
, AllPdu_IDs AS (
    SELECT Mi_Index
         , ROW_NUMBER() OVER(PARTITION BY Mi_Index ORDER BY (SELECT NULL)) AS pdu_Index
         , id.value('.','NVARCHAR(MAX)') AS pdu_id
    FROM AllMessageInfos
    CROSS APPLY TheMI.nodes('message_info/pdu_id') AS a(id)   
)
, AllStatus AS (
    SELECT Mi_Index
         , ROW_NUMBER() OVER(PARTITION BY Mi_Index ORDER BY (SELECT NULL)) AS status_Index
         , id.value('.', 'INT') AS status
    FROM AllMessageInfos
    CROSS APPLY TheMI.nodes('message_info/status') AS a(id)   
)
SELECT i.Mi_Index AS MessageInfoIndex
     , i.id_Index AS SubSetIndex
     , i.id
     , p.pdu_id
     , s.[status]
FROM AllIDs AS i
JOIN AllPdu_IDs AS p ON i.Mi_Index = p.Mi_Index AND i.id_Index = p.pdu_Index
JOIN AllStatus AS s ON i.Mi_Index = s.Mi_Index AND i.id_Index = s.status_Index

SELECT 'Shnugo: ' +  CAST(CAST(GETDATE()-@d AS TIME) AS VARCHAR(100))
GO

蒙特维兹多

DECLARE @d DATETIME = GETDATE()

SELECT 
    m.value('for $i in . return count(../../*[. << $i])', 'INT') AS message_info_position,
    m.value('for $i in . return count(../*[. << $i]) + 1', 'INT') AS internal_position,
    m.value('fn:local-name(.)', 'SYSNAME') AS element_name,
    m.value('.', 'NVARCHAR(4000)') AS element_value
FROM #xml x
CROSS APPLY data.nodes('/response/message_infos/message_info/*') AS A(m)

SELECT 'Montewhizdoh: ' +  CAST(CAST(GETDATE()-@d AS TIME) AS VARCHAR(100))
GO

德瓦特(旧)

DECLARE @d DATETIME = GETDATE()
SELECT
      id = MAX(CASE WHEN name = 'id' THEN val END)
    , pdu_id = MAX(CASE WHEN name = 'pdu_id' THEN val END)
    , [status] = MAX(CASE WHEN name = 'status' THEN val END)
FROM (
    SELECT
          name = t.c.value('local-name(.)', 'SYSNAME')
        , val = t.c.value('.', 'INT')
        , RowNum = ROW_NUMBER() OVER (ORDER BY 1/0)
        , RowNumGroup = ROW_NUMBER() OVER (ORDER BY 1/0) % 3
    FROM #xml x
    CROSS APPLY data.nodes('/response/message_infos/message_info/*') t(c)
) t
GROUP BY RowNum - CASE WHEN RowNumGroup = 0 THEN 3 ELSE RowNumGroup END
SELECT 'Devart (OLD): ' +  CAST(CAST(GETDATE()-@d AS TIME) AS VARCHAR(100))
GO

德瓦特(新)

DECLARE @d DATETIME = GETDATE()
SELECT
      id = MIN(CASE WHEN RowNumGroup = 1 THEN val END)
    , pdu_id = MIN(CASE WHEN RowNumGroup = 2 THEN val END)
    , [status] = MIN(CASE WHEN RowNumGroup = 0 THEN val END)
FROM (
    SELECT
          val = t.c.value('(./text())[1]', 'BIGINT')
        , RowNum = ROW_NUMBER() OVER (ORDER BY 1/0)
        , RowNumGroup = ROW_NUMBER() OVER (ORDER BY 1/0) % 3
    FROM #xml x
    CROSS APPLY data.nodes('/response/message_infos/message_info/*') t(c)
) t
GROUP BY RowNum - CASE WHEN RowNumGroup = 0 THEN 3 ELSE RowNumGroup END

SELECT 'Devart (NEW): ' +  CAST(CAST(GETDATE()-@d AS TIME) AS VARCHAR(100))

性能对比Core i5 4460 3.2GHzDDR3 8GbSQL Server 2014 SP1 Express):

Mikael Eriksson: 00:00:00.327
Shnugo:          00:00:00.913
Montewhizdoh:    00:00:01.680
Devart (OLD):    00:00:00.363
Devart (NEW):    00:00:00.200

【讨论】:

  • 我也喜欢这个。这种用GROUP BY和聚合函数和CASE结合的做法真的很帅……
  • @Pinwar13 是一个小技巧,它不强制执行任何特定顺序...换句话说...1/0SELECT 1SELECT NULL in ORDER BY 按自然顺序对行进行排序; )
  • 我想我克服了您解决方案的一个限制,请查看我的答案。谢谢
  • @Devart,我有点困惑......我的机器是一台相当旧的笔记本电脑,配备 i5-2410M 和 2.3 GHz(GB DD3 RAM)。这 - 肯定 - 比你的慢,但没有那么多......你检查了你的 10.000 行吗?有了这个数量,我的机器显示 Mik 2.7 / Shn 26 !!! / Mon 37 / DOld 8 和 DNew 4.4。这~20 倍慢 并且与您的结果不是线性缩放的......需要提到的一点是,解决方案不会转换为相同的目标类型。您的解决方案应该将值读取为NVARCHAR 并在顶部选择中进行最终转换,不是吗(除非所有值都具有相同的类型)?哎呀!
  • @Devart,我用字母数字 Status 值检查了它。带有BIGINT 的ID 和带有NVARCHAR(100) 的状态。 10.000 行导致 Mik 2.93 / Shn 21.3 / Mon 9.8(没有强制转换到 BIGINT,它们显然花费很多并且没有枢轴)/ DOld 12.3 和 DNew 8.2。所以无论如何 Mikaels 的解决方案似乎是最好的,如果一个人只想从上到下阅读所有的价值观...... Cheerio!
【解决方案2】:

这不是答案,只是性能比较!

我真正喜欢 SO 的是不同人提供的各种解决方案。这里有 4 个答案,每个答案都遵循完全不同的概念。

我很好奇他们的表现如何。这是我的结果:

  1. Mikael Eriksson 在 ~1.4 秒内
  2. Shnugo 大约 4.8 秒
  3. montewhizdoh 在 8.8 秒内 但尚未转轴!!
  4. 在 11.3 秒内撤离

由于采用了所有节点,通过 XML 读取自上而下的方法显然比使用大量来回导航的方法更快。可能是,一些解决方案可以改进......

令我惊讶的是,GROUP BY with MAX and CASE 速度很慢...

这是代码:

CREATE TABLE #tmp (ID INT IDENTITY,XmlContent XML);
GO
INSERT INTO #tmp(XmlContent)
SELECT('<response>
  <message_infos>
    <message_info>
      <id>397300589</id>
      <pdu_id>673399673</pdu_id>
      <status>12</status>
      <id>397300589</id>
      <pdu_id>673399675</pdu_id>
      <status>12</status>
    </message_info>
    <message_info>
      <id>397300591</id>
      <pdu_id>673399669</pdu_id>
      <status>12</status>
      <id>397300591</id>
      <pdu_id>673399671</pdu_id>
      <status>12</status>
    </message_info>
    <message_info>
      <id>3973005891</id>
      <pdu_id>6733996732</pdu_id>
      <status>123</status>
      <id>3973005894</id>
      <pdu_id>6733996755</pdu_id>
      <status>126</status>
      <id>3973005897</id>
      <pdu_id>6733996738</pdu_id>
      <status>129</status>
      <id>39730058912</id>
      <pdu_id>67339967513</pdu_id>
      <status>12</status>
    </message_info>
  </message_infos>
</response>');
GO 1000


--Mikael Eriksson 1,4
DECLARE @d DATETIME = GETDATE();
WITH Numbers AS (SELECT N FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) as tbl(N)) 
select T.X.value('(id/text())[sql:column("N.N")][1]', 'nvarchar(max)') as id,
       T.X.value('(pdu_id/text())[sql:column("N.N")][1]', 'nvarchar(max)') as pdu_id,
       T.X.value('(status/text())[sql:column("N.N")][1]', 'int') as status
from #tmp
CROSS APPLY XmlContent.nodes('/response/message_infos/message_info') as T(X)
  cross apply (SELECT TOP(T.X.value('count(id)', 'int')) N FROM Numbers) AS N(N)

SELECT 'Mikael Eriksson: ' +  CAST(CAST(GETDATE()-@d AS TIME) AS VARCHAR(100));
GO

--Shnugo 4.8 Sekunden
DECLARE @d DATETIME = GETDATE();
WITH AllMessageInfos AS
(
    SELECT  ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) AS Mi_Index
           ,mi.query('.') AS TheMI
    FROM #tmp
    CROSS APPLY XmlContent.nodes('/response/message_infos/message_info') AS A(mi)
)
,AllIDs AS
(
    SELECT Mi_Index
          ,ROW_NUMBER() OVER(PARTITION BY Mi_Index ORDER BY (SELECT NULL)) AS id_Index
          ,id.value('.','nvarchar(max)') AS id
    FROM AllMessageInfos
    CROSS APPLY TheMI.nodes('message_info/id') AS a(id)   
)
,AllPdu_IDs AS
(
    SELECT Mi_Index
          ,ROW_NUMBER() OVER(PARTITION BY Mi_Index ORDER BY (SELECT NULL)) AS pdu_Index
          ,id.value('.','nvarchar(max)') AS pdu_id
    FROM AllMessageInfos
    CROSS APPLY TheMI.nodes('message_info/pdu_id') AS a(id)   
)
,AllStatus AS
(
    SELECT Mi_Index
          ,ROW_NUMBER() OVER(PARTITION BY Mi_Index ORDER BY (SELECT NULL)) AS status_Index
          ,id.value('.','int') AS status
    FROM AllMessageInfos
    CROSS APPLY TheMI.nodes('message_info/status') AS a(id)   
)
SELECT i.Mi_Index AS MessageInfoIndex
      ,i.id_Index AS SubSetIndex
      ,i.id
      ,p.pdu_id
      ,s.status
FROM AllIDs AS i
INNER JOIN AllPdu_IDs AS p ON i.Mi_Index=p.Mi_Index AND i.id_Index=p.pdu_Index
INNER JOIN AllStatus AS s ON i.Mi_Index=s.Mi_Index AND i.id_Index=s.status_Index

SELECT 'Shnugo: ' +  CAST(CAST(GETDATE()-@d AS TIME) AS VARCHAR(100));
GO

--Montewizdoh 8.8 Sekunden
DECLARE @d DATETIME = GETDATE();
SELECT 
m.value('for $i in . return count(../../*[. << $i])', 'int') as message_info_position,
m.value('for $i in . return count(../*[. << $i]) + 1', 'int') as internal_position,
m.value('fn:local-name(.)', 'SYSNAME') as element_name,
m.value('.', 'nvarchar(4000)') as element_value
FROM #tmp
CROSS APPLY XmlContent.nodes('/response/message_infos/message_info/*') AS A(m)
SELECT 'Montewhizdoh: ' +  CAST(CAST(GETDATE()-@d AS TIME) AS VARCHAR(100));
GO

--Devart 11.3 Sec
DECLARE @d DATETIME = GETDATE();
SELECT
      id = MAX(CASE WHEN name = 'id' THEN val END)
    , pdu_id = MAX(CASE WHEN name = 'pdu_id' THEN val END)
    , [status] = MAX(CASE WHEN name = 'status' THEN val END)
FROM (
    SELECT
          name = t.c.value('local-name(.)', 'SYSNAME')
        , val = t.c.value('.', 'nvarchar(max)')
        , RowNum = ROW_NUMBER() OVER (ORDER BY 1/0)
        , RowNumGroup = ROW_NUMBER() OVER (ORDER BY 1/0) % 3
    FROM #tmp
    CROSS APPLY XmlContent.nodes('/response/message_infos/message_info/*') t(c)
) t
GROUP BY RowNum - CASE WHEN RowNumGroup = 0 THEN 3 ELSE RowNumGroup END
SELECT 'Devart: ' +  CAST(CAST(GETDATE()-@d AS TIME) AS VARCHAR(100));

GO

DROP TABLE #tmp;

【讨论】:

  • 感谢您的努力。我想在我的例子中是一些溢出到 tempdb :)
  • 谢谢,Shnugo,我从你的关于性能测试的帖子中学到了很多!
【解决方案3】:

我提出以下建议供您考虑。您可能需要旋转结果,但结果具有足够的意义,可以按原样进行编程。

message_info_position 告诉您值来自哪个 message_info 以及 local_position 告诉你在 message_info 中的位置

我认为您会发现此解决方案相当健壮,并且能够处理奇怪形状的数据。

希望对你有帮助!

DECLARE @ixml XML=
'<response>
  <message_infos>
    <message_info>
      <id>397300589</id>
      <pdu_id>673399673</pdu_id>
      <status>12</status>
      <id>397300589</id>
      <pdu_id>673399675</pdu_id>
      <status>12</status>
    </message_info>
    <message_info>
      <id>397300591</id>
      <pdu_id>673399669</pdu_id>
      <id>397300591</id>
      <pdu_id>673399671</pdu_id>
      <status>12</status>
    </message_info>
    <message_info>
      <id>3973005891</id>
      <pdu_id>6733996732</pdu_id>
      <status>123</status>
      <id>3973005894</id>
      <pdu_id>6733996755</pdu_id>
      <status>126</status>
      <id>3973005897</id>
      <pdu_id>6733996738</pdu_id>
      <status>129</status>
      <id>39730058912</id>
      <pdu_id>67339967513</pdu_id>
    <pdu_id>67339967513x</pdu_id>
    <pdu_id>67339967513y</pdu_id>
      <status>12</status>
    </message_info>
  </message_infos>
</response>';

SELECT 
 row_number() over(order by A.m) as internal_position,
 CHECKSUM(m.value('..', 'nvarchar(max)')) as message_info_position,
 m.value('fn:local-name(.)', 'SYSNAME') as element_name,
 m.value('.', 'nvarchar(4000)') as element_value
FROM @ixml.nodes('/response/message_infos/message_info/*') AS A(m)

【讨论】:

  • 嗨,montewhizdoh,我刚刚发布了一个性能比较的答案......除了这个解决方案的性能不是最好的事实之外,我真的很感谢这个棘手的代码!从我这边+1!我从来没有见过这个:[. &lt;&lt; $i]。你能给我解释一下吗?也许你有一个链接?
  • 您好 Shnugo,感谢您的性能比较。我修改了代码以使用一种方法来减少 dom 遍历(提高性能),同时保持我的解决方案的稳健性。
  • Shnugo,这里的答案解释了语法和关于 O(n^2) 效率的警告。我向大家道歉,因为我没有先测试我的表现,当时我完全只专注于实现准确性。我倾向于先“让事情发挥作用”,然后再优化stackoverflow.com/questions/1134075/…
【解决方案4】:

首先:FROM OPENXML 已经过时了!你最好使用 real XML 方法...

更新

根据您的评论,我建议这样做:您阅读编号集中的所有标签,并将它们与它们在子集中的索引一起拼图。

我在第二个 message_info 中添加了第三组来测试这个...

DECLARE @ixml XML=
'<response>
  <message_infos>
    <message_info>
      <id>397300589</id>
      <pdu_id>673399673</pdu_id>
      <status>12</status>
      <id>397300589</id>
      <pdu_id>673399675</pdu_id>
      <status>12</status>
    </message_info>
    <message_info>
      <id>397300591</id>
      <pdu_id>673399669</pdu_id>
      <status>12</status>
      <id>397300591</id>
      <pdu_id>673399671</pdu_id>
      <status>12</status>
      <id>1111</id>
      <pdu_id>2222</pdu_id>
      <status>33</status>
    </message_info>
  </message_infos>
</response>';

WITH AllMessageInfos AS
(
    SELECT  ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) AS Mi_Index
           ,mi.query('.') AS TheMI
    FROM @ixml.nodes('/response/message_infos/message_info') AS A(mi)
)
,AllIDs AS
(
    SELECT Mi_Index
          ,ROW_NUMBER() OVER(PARTITION BY Mi_Index ORDER BY (SELECT NULL)) AS id_Index
          ,id.value('.','bigint') AS id
    FROM AllMessageInfos
    CROSS APPLY TheMI.nodes('message_info/id') AS a(id)   
)
,AllPdu_IDs AS
(
    SELECT Mi_Index
          ,ROW_NUMBER() OVER(PARTITION BY Mi_Index ORDER BY (SELECT NULL)) AS pdu_Index
          ,id.value('.','bigint') AS pdu_id
    FROM AllMessageInfos
    CROSS APPLY TheMI.nodes('message_info/pdu_id') AS a(id)   
)
,AllStatus AS
(
    SELECT Mi_Index
          ,ROW_NUMBER() OVER(PARTITION BY Mi_Index ORDER BY (SELECT NULL)) AS status_Index
          ,id.value('.','int') AS status
    FROM AllMessageInfos
    CROSS APPLY TheMI.nodes('message_info/status') AS a(id)   
)
SELECT i.Mi_Index AS MessageInfoIndex
      ,i.id_Index AS SubSetIndex
      ,i.id
      ,p.pdu_id
      ,s.status
FROM AllIDs AS i
INNER JOIN AllPdu_IDs AS p ON i.Mi_Index=p.Mi_Index AND i.id_Index=p.pdu_Index
INNER JOIN AllStatus AS s ON i.Mi_Index=s.Mi_Index AND i.id_Index=s.status_Index

上一页

似乎很奇怪,每个 message_info 下都有两组相同的标签。你可以这样做:

DECLARE @ixml XML=
'<response>
  <message_infos>
    <message_info>
      <id>397300589</id>
      <pdu_id>673399673</pdu_id>
      <status>12</status>
      <id>397300589</id>
      <pdu_id>673399675</pdu_id>
      <status>12</status>
    </message_info>
    <message_info>
      <id>397300591</id>
      <pdu_id>673399669</pdu_id>
      <status>12</status>
      <id>397300591</id>
      <pdu_id>673399671</pdu_id>
      <status>12</status>
    </message_info>
  </message_infos>
</response>';

SELECT m.value('id[1]','bigint') AS id
      ,m.value('pdu_id[1]','bigint') AS pdu_id
      ,m.value('status[1]','int') AS status
FROM @ixml.nodes('/response/message_infos/message_info') AS A(m)
UNION ALL
SELECT m.value('id[2]','bigint') AS id
      ,m.value('pdu_id[2]','bigint') AS pdu_id
      ,m.value('status[2]','int') AS status
FROM @ixml.nodes('/response/message_infos/message_info') AS A(m)

【讨论】:

  • 我同意,这个 xml 文件不行。但是“message_info”中的项目数量不固定。看起来没有简单的方法可以解决这个任务。
  • @R.Gravis 有已知的最大值吗?
  • @R.Gravis 是否总是一个接一个地设置所有三个标签?
  • @Shnugo 很好的实现 :) 顺便说一句,如果至少有一个标签不可用,我的情况将无法正常工作
  • @Devart 嗨,我的方法在这种情况下也有一个很大的缺陷:由于子集被它们的位置绑定在一起,这会配对错误的条目......但是 OP 说 标签集是固定的...更重要的-也许-是,您的方法不会从message_info获取数据。
【解决方案5】:

您可以使用数字表来获取第 n 个值。 这当然不依赖于未定义的 order by 语句,但它确实要求所有元素在每个 message_info 元素中出现相同的次数。

这里我使用了一个 10 行的静态数字表。

select T.X.value('(id/text())[sql:column("N.N")][1]', 'int') as id,
       T.X.value('(pdu_id/text())[sql:column("N.N")][1]', 'int') as pdu_id,
       T.X.value('(status/text())[sql:column("N.N")][1]', 'int') as status
from @x.nodes('/response/message_infos/message_info') as T(X)
  cross apply (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) as N(N)
where N.N <= T.X.value('count(id)', 'int')

【讨论】:

  • 非常有趣的解决方案。谢谢你:)
猜你喜欢
  • 2011-08-09
  • 2010-09-22
  • 2021-05-17
  • 2018-02-19
  • 2018-03-23
  • 2020-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多