Frage

Ich versuche, mithilfe von "FOR XML" ein XML-Dokument aus der SQL Server 2005-Datenbank zu generieren konstruieren.

Es gibt zwei einfache Tabellen in der Datenbank mit einem Eins-zu-viele-Beziehung:

1) Zeitschriften

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

2) Artikel

 | 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  |

Nehmen wir an, ich alle Zeitschriften finden, die einen Artikel mit einer Größe von mehr als 1000 haben und die folgenden XML zu erzeugen:

<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>

Ich versuche, solche XML zu erzeugen, indem eine „PATH“ Modus:

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

Es wird die folgende XML erzeugen:

<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>

Es gibt also zwei Elemente für die Magazine mit Id = „54“ (einem für jeden Artikel), und das ist das Problem.

Ich kann die Abfrage mit einer Unterabfrage wie folgt umschreiben:

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

Und diese produzieren die folgende 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>

Aber durch eine Unterabfrage kann ich nicht Zeitschriften von Artikel Säulen (ohne komplexe zusätzliche Abfragen) filtern.

Der "FOR XML AUTO" -Modus ist nicht geeignet, weil es sehr einfach ist und nicht einige "PATH" Merkmale (wie Attribute mit @, ROOT, etc ..)

unterstützt

So, Gibt es eine Möglichkeit, in "PATH" -Modus Gruppe innerer Tabellendaten wie in "AUTO" -Modus?

Danke!

War es hilfreich?

Lösung

Nun können Sie einen Schritt näher kommen, indem die „Größe> 1000“ innerhalb Ihrer Unterabfrage festgelegt wird:

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

Was Sie jetzt fehlt, ist die Tatsache Sie noch Zeitschriften, die keine Artikel mit einer Größe haben bekommen> 1000. Sie können diese so etwas wie dieses beseitigen:

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

(ungetestet, ich habe nicht einen SQL-Server zur Hand jetzt haben).

Ist für Sie das? Macht es Ihnen die Zeitschriften und Artikel Sie suchen?

Marc

Andere Tipps

Verwenden Sie FOR XML explizit. Am längsten ist, Code zu schreiben, aber die Performance-Probleme provozieren von Unterabfragen zu verschwinden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top