2016-09-19 84 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