2016-09-19 83 views
2

在SQL Server表中,我有一个XML列,其中状态发生(首先是最早的,最后一个当前状态)。SQL Server中XML列的反向顺序

我必须编写一个返回状态的存储过程:最新的第一个,最旧的最后一个。

这是我写的:价值

ALTER PROCEDURE [dbo].[GetDeliveryStatus] 
    @invoiceID nvarchar(255) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @xml xml 
    SET @xml = (SELECT statusXML 
       FROM Purchase 
       WHERE invoiceID = @invoiceID) 

    SELECT 
     t.n.value('text()[1]', 'nvarchar(50)') as DeliveryStatus 
    FROM 
     @xml.nodes('/statuses/status') as t(n) 
    ORDER BY 
     DeliveryStatus DESC 
END 

例如,在statusXML列:

<statuses> 
    <status>A</status> 
    <status>B</status> 
    <status>A</status> 
    <status>B</status> 
    <status>C</status> 
</statuses> 

我想程序返回的:

C 
B 
A 
B 
A 

ORDER BY .... DESC它的回报ALPHABETIC逆转(C B B A A

我应该如何纠正我的程序?

+2

你需要有东西不仅仅是'status'值更多 - 些时间和日期,一些连续增加'ID'或类似的东西,然后你就可以申请了'ORDER BY :... DESC' ... –

+0

我同意,我也建议至少添加状态更改的日期,但我不是数据库的所有者。任何方式颠倒XML的隐式顺序是我的问题。 –

回答

0

没有必要首先声明一个变量。你可以(你应该!)直接从表列中读取所需的值。最好成绩是内嵌表值函数(而不是SP只是阅读东西......)

  • 更好的性能
  • inlineable
  • 您可以一次
  • 集查询许多InvoiceIDs - 基

试试这个(我放弃模拟表 - 真正的数据!):

CREATE TABLE Purchase(ID INT IDENTITY,statusXML XML, InvocieID INT, OtherValues VARCHAR(100)); 
INSERT INTO Purchase VALUES('<statuses> 
    <status>A</status> 
    <status>B</status> 
    <status>A</status> 
    <status>B</status> 
    <status>C</status> 
</statuses>',100,'Other values of your row'); 
GO 

WITH NumberedStatus AS 
(
    SELECT ID 
      ,InvocieID 
      , ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nr 
      ,stat.value('.','nvarchar(max)') AS [Status] 
      ,OtherValues 
    FROM Purchase 
    CROSS APPLY statusXML.nodes('/statuses/status') AS A(stat) 
    WHERE InvocieID=100 
) 
SELECT * 
FROM NumberedStatus 
ORDER BY Nr DESC 
GO 
--Clean-Up 
--DROP TABLE Purchase; 

结果

+---+-----+---+---+--------------------------+ 
| 1 | 100 | 5 | C | Other values of your row | 
+---+-----+---+---+--------------------------+ 
| 1 | 100 | 4 | B | Other values of your row | 
+---+-----+---+---+--------------------------+ 
| 1 | 100 | 3 | A | Other values of your row | 
+---+-----+---+---+--------------------------+ 
| 1 | 100 | 2 | B | Other values of your row | 
+---+-----+---+---+--------------------------+ 
| 1 | 100 | 1 | A | Other values of your row | 
+---+-----+---+---+--------------------------+ 
+0

感谢这个非常明确的答案! –

1

根据现有的顺序为节点创建一个序列,然后将其逆转。

WITH [x] AS (
    SELECT 
     t.n.value('text()[1]', 'nvarchar(50)') as DeliveryStatus 
     ,ROW_NUMBER() OVER (ORDER BY t.n.value('..', 'NVARCHAR(100)')) AS [Order] 
    FROM 
     @xml.nodes('/statuses/status') as t(n) 
) 
    SELECT 
     DeliveryStatus 
    FROM [x] 
    ORDER BY [x].[Order] DESC 

...结果...

DeliveryStatus 
C 
B 
A 
B 
A 
+0

在你的OVER(ORDER BY ...)中使用'(SELECT NULL)'更容易...... XML的隐式顺序允许这种最快的方法...并且不需要'.value('text( )[1]','...')',一个简单的'.value('。','...')'就足够了...... – Shnugo