2009-09-18 44 views
1

我想通過使用「FOR XML」構造從SQL Server 2005數據庫生成XML文檔。SQL Server 2005「FOR XML PATH」分組

有數據庫中的兩個簡單的表有一個一對多的關係:

1)雜誌

| Id | Number | Name  | 
---------------------------- 
| 53 | 0001 | Magazine 1 | 
| 54 | 0002 | Magazine 2 | 
| 55 | 0003 | Magazine 3 | 

2)文章

| Id | Title | MagazineId | Size | 
-------------------------------------- 
| 1 | Article 1 |  53 | 1205 | 
| 2 | Article 2 |  53 | 817 | 
| 3 | Article 3 |  54 | 1570 | 
| 4 | Article 4 |  54 | 2510 | 
| 5 | Article 5 |  55 | 910 | 

假設我有找到所有尺寸大於1000 的文章並生成以下xml:

<Magazines> 
    <Magazine Id="53"> 
     <Number>0001</Number> 
     <Articles> 
     <Article Id="1"> 
      <Title>Article 1</Title> 
      <Size>1205</Size> 
     </Article> 
     </Articles> 
    </Magazine> 
    <Magazine Id="54"> 
     <Number>0002</Number> 
     <Articles> 
     <Article Id="3"> 
      <Title>Article 3</Title> 
      <Size>1570</Size> 
     </Article> 
     <Article Id="4"> 
      <Title>Article 4</Title> 
      <Size>2510</Size> 
     </Article> 
     </Articles> 
    </Magazine> 
</Magazines> 

我試圖通過使用 「PATH」 模式產生這樣的XML:

SELECT Magazines.Id AS "@Id", 
     Magazines.Number AS "Number", 
     Articles.Id AS "Articles/Article/@Id", 
     Articles.Title AS "Articles/Article/Title", 
     Articles.Size AS "Articles/Article/Size" 
FROM Magazines INNER JOIN Articles ON Magazines.Id = Articles.MagazineId 
WHERE Articles.Size > 1000 
FOR XML PATH('Magazine'), ROOT('Magazines'), TYPE 

這將產生以下XML:

<Magazines> 
    <Magazine Id="53"> 
    <Number>0001</Number> 
    <Articles> 
     <Article Id="1"> 
     <Title>Article 1</Title> 
     <Size>1205</Size> 
     </Article> 
    </Articles> 
    </Magazine> 
    <Magazine Id="54"> 
    <Number>0002</Number> 
    <Articles> 
     <Article Id="3"> 
     <Title>Article 3</Title> 
     <Size>1570</Size> 
     </Article> 
    </Articles> 
    </Magazine> 
    <Magazine Id="54"> 
    <Number>0002</Number> 
    <Articles> 
     <Article Id="4"> 
     <Title>Article 4</Title> 
     <Size>2510</Size> 
     </Article> 
    </Articles> 
    </Magazine> 
</Magazines> 

因此,有對雜誌兩種元素與Id =「54」(每篇文章一個),這就是問題所在。

我可以用這樣的子查詢重寫查詢:

SELECT M.Id AS "@Id", 
     M.Number AS "Number", 
    (SELECT Articles.Id AS "@Id", 
       Articles.Title AS "Title", 
       Articles.Size AS "Size" 
    FROM Articles 
    WHERE Articles.MagazineId = M.Id 
    FOR XML PATH('Article'), ROOT('Articles'), TYPE 
    ) 
FROM Magazines AS M 
FOR XML PATH('Magazine'), ROOT('Magazines'), TYPE 

這產生以下XML:

<Magazines> 
    <Magazine Id="53"> 
    <Number>0001</Number> 
    <Articles> 
     <Article Id="1"> 
     <Title>Article 1</Title> 
     <Size>1205</Size> 
     </Article> 
     <Article Id="2"> 
     <Title>Article 2</Title> 
     <Size>817</Size> 
     </Article> 
    </Articles> 
    </Magazine> 
    <Magazine Id="54"> 
    <Number>0002</Number> 
    <Articles> 
     <Article Id="3"> 
     <Title>Article 3</Title> 
     <Size>1570</Size> 
     </Article> 
     <Article Id="4"> 
     <Title>Article 4</Title> 
     <Size>2510</Size> 
     </Article> 
    </Articles> 
    </Magazine> 
    <Magazine Id="55"> 
    <Number>0003</Number> 
    <Articles> 
     <Article Id="5"> 
     <Title>Article 5</Title> 
     <Size>910</Size> 
     </Article> 
    </Articles> 
    </Magazine> 
</Magazines> 

但是,通過使用子查詢,我不能過濾由文章列雜誌(沒有複雜的附加查詢)。

的「FOR XML AUTO」模式是不適合的,因爲它是非常簡單的,不支持一些「PATH」功能(如使用@,ROOT等屬性。)

那麼,有沒有什麼在「路徑」模式下將內部表格數據分組,如「自動」模式?

謝謝!

回答

1

好了,你可以得到一個更近了一步,通過指定的子查詢裏面的「大小> 1000」:

SELECT M.Id AS "@Id", 
     M.Number AS "Number", 
    (SELECT Articles.Id AS "@Id", 
       Articles.Title AS "Title", 
       Articles.Size AS "Size" 
    FROM Articles 
    WHERE Articles.MagazineId = M.Id 
      AND Articles.Size > 1000 
    FOR XML PATH('Article'), ROOT('Articles'), TYPE 
    ) 
FROM Magazines AS M 
FOR XML PATH('Magazine'), ROOT('Magazines'), TYPE 

什麼你現在缺少的是事實,你仍然會得到一些沒有文章的雜誌與中尺寸> 1000,您可以消除這些東西是這樣的:

SELECT M.Id AS "@Id", 
     M.Number AS "Number", 
    (SELECT Articles.Id AS "@Id", 
       Articles.Title AS "Title", 
       Articles.Size AS "Size" 
     FROM Articles 
     WHERE Articles.MagazineId = M.Id 
      AND Articles.Size > 1000 
     FOR XML PATH('Article'), ROOT('Articles'), TYPE 
    ) 
FROM Magazines AS M 
WHERE EXISTS(SELECT * FROM Articles 
      WHERE Articles.MagazineId = M.Id 
       AND Articles.Size > 1000) 
FOR XML PATH('Magazine'), ROOT('Magazines'), TYPE 

(未經測試,我不手邊有一個SQL服務器現在)。

這是否適合您?它是否爲您提供您正在尋找的雜誌和文章?

Marc

+0

嗨,馬克!感謝您的幫助!你的查詢工作得很好,但不幸的是,子查詢導致了SQL方面的一些性能問題。所以,我們決定在應用服務器端構建xml。不管怎麼說,還是要謝謝你! – junglit 2009-09-21 08:37:55

0

使用FOR XML顯式。是最長的代碼編寫,但消除了子查詢挑戰的性能問題。