문제

"for xml"construct를 사용하여 SQL Server 2005 데이터베이스에서 XML 문서를 생성하려고합니다.

데이터베이스에는 일대일 관계가있는 두 개의 간단한 테이블이 있습니다.

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>

"경로"모드를 사용하여 이러한 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>

그러나 하위 쿼리를 사용하면 기사 열로 잡지를 필터링 할 수 없습니다 (복잡한 추가 쿼리없이).

"XML Auto"모드는 매우 간단하고 일부 "경로"기능 ( @, root 등을 사용한 속성 등)을 지원하지 않기 때문에 적합하지 않습니다.

그렇다면 "Auto"모드와 같이 "Path"모드에 내부 테이블 데이터를 그룹화 할 가능성이 있습니까?

고맙습니다!

도움이 되었습니까?

해결책

글쎄, 하위 퀘스트 내부에 "크기> 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 서버가 없습니다).

그게 당신에게 효과가 있습니까? 당신이 찾고있는 잡지와 기사를 제공합니까?

마크

다른 팁

XML 명시 적용 사용. 작성하는 가장 긴 코드이지만 하위 쿼리로 성능 문제가 사라집니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top