2013-12-02 5 views
0

Я пытаюсь получить данные из таблицы (SQL Server 2008 R2) в формате XML и, похоже, не может превратить ее в идеальную структуру. Я пробовал различные режимы FOR XML и методы объединения, но у меня есть минимальный опыт работы с XML и до этого не работал с XML-выходом через SQL.Как управлять выходным форматом XML в SQL

Мои данные в таблицу с именем XMLResults со следующей структурой:

ResultID Country Product Disposition Results 
----------------------------------------------- 
1   UK  ABC  Result1  100 
2   UK  ABC  Result2  200 
3   UK  ABC  Result3  300 
4   UK  XYZ  Result1  100 
5   UK  XYZ  Result2  200 
6   UK  XYZ  Result3  300 
7   USA  ABC  Result1  100 
8   USA  ABC  Result2  200 
9   USA  ABC  Result3  300 
10   USA  XYZ  Result1  100 
11   USA  XYZ  Result2  200 
12   USA  XYZ  Result3  300 

В настоящее время у меня есть этот запрос:

SELECT (SELECT Country, 
       (SELECT Product, 
         (SELECT Disposition, Results 
          FROM XMLResults t1 
          WHERE t1.ResultID = t2.ResultID 
          FOR XML PATH ('Dispositions'), TYPE, ELEMENTS 
         ) 
        FROM XMLResults t2 
        WHERE t2.ResultID = t3.ResultID 
        FOR XML PATH ('Products'), TYPE, ELEMENTS 
       ) 
      FROM XMLResults t3 
     ORDER BY Country, Product 
      FOR XML PATH ('Countries'), TYPE, ELEMENTS 
     ) 
    FOR XML PATH('Stats'); 

который возвращает XML, как это:

<Stats> 
    <Countries> 
    <Country>UK</Country> 
    <Products> 
     <Product>ABC</Product> 
     <Dispositions> 
     <Disposition>Result1</Disposition> 
     <Results>100</Results> 
     </Dispositions> 
    </Products> 
    </Countries> 
    <Countries> 
    <Country>UK</Country> 
    <Products> 
     <Product>ABC</Product> 
     <Dispositions> 
     <Disposition>Result2</Disposition> 
     <Results>200</Results> 
     </Dispositions> 
    </Products> 
    </Countries> 
    <Countries> 
    <Country>UK</Country> 
    <Products> 
     <Product>ABC</Product> 
     <Dispositions> 
     <Disposition>Result3</Disposition> 
     <Results>300</Results> 
     </Dispositions> 
    </Products> 
    </Countries> 
    ... 
</Stats> 

Не страшно, но я бы предпочел, чтобы он не упал полностью обратно на уровень «Страны» после каждого результата и пробовал также не нужны дополнительные общие теги.

Нечто подобное было бы лучше:

<Stats> 
    <Countries> 
    <Country = "UK"> 
     <Products> 
     <Product = "ABC"> 
      <Dispositions> 
      <Disposition> 
       <ReasonCode>Result1</ReasonCode> 
       <Count>100</Count> 
      </Disposition> 
      <Disposition> 
       <ReasonCode>Result2</ReasonCode> 
       <Count>200</Count> 
      </Disposition> 
      <Disposition> 
       <ReasonCode>Result3</ReasonCode> 
       <Count>300</Count> 
      </Disposition> 
      </Dispositions> 
     </Product> 
     ... 
     </Products> 
    </Country> 
    ... 
    </Countries> 
</Stats> 

Может быть, даже что-то вроде этого (выглядит немного чище):

<Stats> 
    <Country = "UK"> 
    <Product = "ABC"> 
     <Disposition ReasonCode = "Result1" Count = "100" /> 
     <Disposition ReasonCode = "Result2" Count = "200" /> 
     <Disposition ReasonCode = "Result3" Count = "300" /> 
    </Product> 
    <Product = "XYZ"> 
     <Disposition ReasonCode = "Result1" Count = "100" /> 
     <Disposition ReasonCode = "Result2" Count = "200" /> 
     <Disposition ReasonCode = "Result3" Count = "300" /> 
    </Product> 
    </Country> 
    <Country = "USA"> 
    <Product = "ABC"> 
     <Disposition ReasonCode = "Result1" Count = "100" /> 
     <Disposition ReasonCode = "Result2" Count = "200" /> 
     <Disposition ReasonCode = "Result3" Count = "300" /> 
    </Product> 
    <Product = "XYZ"> 
     <Disposition ReasonCode = "Result1" Count = "100" /> 
     <Disposition ReasonCode = "Result2" Count = "200" /> 
     <Disposition ReasonCode = "Result3" Count = "300" /> 
    </Product> 
    </Country> 
</Stats> 

Формат вывода не установлен в камне, так что если есть рекомендации, я также открыт для предложений по этому поводу.

Спасибо, Шон


Редактирование данных образца:

CREATE TABLE XMLResults (
     ResultID BIGINT IDENTITY(1,1) NOT NULL 
    , Country VARCHAR(50) NOT NULL 
    , Product VARCHAR(50) NOT NULL 
    , Disposition VARCHAR(50) NOT NULL 
    , Results INT NOT NULL); 

INSERT INTO XMLResults (Country, Product, Disposition, Results) 
VALUES ('UK', 'ABC', 'Result1', 100) 
    , ('UK', 'ABC', 'Result2', 200) 
    , ('UK', 'ABC', 'Result3', 300) 
    , ('UK', 'XYZ', 'Result1', 100) 
    , ('UK', 'XYZ', 'Result2', 200) 
    , ('UK', 'XYZ', 'Result3', 300) 
    , ('USA', 'ABC', 'Result1', 100) 
    , ('USA', 'ABC', 'Result2', 200) 
    , ('USA', 'ABC', 'Result3', 300) 
    , ('USA', 'XYZ', 'Result1', 100) 
    , ('USA', 'XYZ', 'Result2', 200) 
    , ('USA', 'XYZ', 'Result3', 300); 
+0

Было бы очень полезно создать [SQL Fiddle] (http://www.sqlfiddle.com), который создает таблицы и вставляет в них некоторые примеры данных. –

ответ

1

Если вы хотите атрибут ориентированных на XML, снабдите '@' к псевдонимами столбцов. Вы можете полностью настроить выход, например:

SELECT 
    Country [@Country], 
    (SELECT 
    Product [@Product], 
    (SELECT 
     Disposition [@ReasonCode], 
     Results [@Count] 
    FROM #XMLResults t3 
    WHERE t3.Country = t1.Country AND t3.Product = t2.Product 
    FOR XML PATH('Disposition'),TYPE) 
    FROM #XMLResults t2 
    WHERE t2.Country = t1.Country 
    GROUP BY Product 
    FOR XML PATH('Product'),TYPE) 
FROM #XMLResults t1 
GROUP BY Country 
FOR XML PATH('Country'), ROOT ('Stats') 

Просто поиграйте с ним.

+0

Это замечательно, за исключением того, что это дублирует раздел «Продукт» по количеству Расположений для этого продукта. В данных выборки для каждого продукта есть 3 результата, поэтому каждый продукт для каждой страны отображается 3 раза (а не только один раз с 3 результатами). Есть ли способ обойти это? Я еще не смог найти решение. – Sean

+0

Ответ изменен в соответствии с требованиями. Я добавил GROUP BY Product для t2 – Anon

Смежные вопросы