В следующий раз, пожалуйста, предоставьте некоторые примеры данных в формате расходных материалов, лучше всего использовать DDL, INSERT и ваш рабочий код как автономный MCVE .Это очень помогает.На этот раз я набрал его для вас:
Некоторые таблицы макетов с данными:
DECLARE @Product TABLE(ProductKey INT IDENTITY,Color VARCHAR(100),EnglishProductName VARCHAR(100),ProductSubcategoryKey INT);
INSERT INTO @Product VALUES('Black','Full-Finger Gloves, L',1)
,('Black','Full-Finger Gloves, M',1)
,('Black','Full-Finger Gloves, S',1)
,('Black','Half-Finger Gloves, L',1)
,('Black','Half-Finger Gloves, M',1)
,('Black','Half-Finger Gloves, S',1);
DECLARE @ProductSubCategory TABLE(ProductSubcategoryKey INT IDENTITY,EnglishProductSubcategoryName VARCHAR(100));
INSERT INTO @ProductSubCategory VALUES('Gloves');
- в запросе используется FOR XML PATH
вместо режима AUTO
.Я объясню это позже
Select Distinct Product.Color AS [@Color]
, Product.EnglishProductName AS [@EnglishProductName]
, 0 as [@Customizable]
, ProductSubCategory.EnglishProductSubcategoryName AS [ProductSubCategory/@EnglishProductSubcategoryName]
From @Product as Product
Inner Join @ProductSubCategory As ProductSubCategory On ProductSubCategory.ProductSubcategoryKey = Product.ProductSubcategoryKey
UNION
Select Distinct Product.Color AS [@Color]
, Product.EnglishProductName AS [@EnglishProductName]
, 1 as [@Customizable]
, ProductSubCategory.EnglishProductSubcategoryName AS [ProductSubCategory/@EnglishProductSubcategoryName]
From @Product as Product
Inner Join @ProductSubCategory As ProductSubCategory On ProductSubCategory.ProductSubcategoryKey = Product.ProductSubcategoryKey
For Xml PATH('Product');
Некоторое объяснение:
Ваш подход с AUTO
позволяет двигателю решить, что вы получите.Вообще мне не нравится такая идея.Любое изменение внутренней реализации может взорвать систему в производстве.Лучше использовать PATH
, что дает вам самый глубокий контроль над тем, что вы получите.
Некоторые замечания:
Объединение не требуется
ЕслиЯ правильно понял, вы используете UNION
просто для добавления каждого продукта дважды.Одна строка с нулем в @Customizable
, вторая с 1. Простой CROSS JOIN
с набором VALUES
будет делать то же самое, но быстрее и лучше читать:
Select Distinct Product.Color AS [@Color]
, Product.EnglishProductName AS [@EnglishProductName]
, A.Customizable as [@Customizable]
, ProductSubCategory.EnglishProductSubcategoryName AS [ProductSubCategory/@EnglishProductSubcategoryName]
From @Product as Product
Inner Join @ProductSubCategory As ProductSubCategory On ProductSubCategory.ProductSubcategoryKey = Product.ProductSubcategoryKey
CROSS JOIN (VALUES(1),(0)) A(Customizable)
For Xml PATH('Product')
Удобочитаемость
Хорошо использовать псевдонимы таблиц, но я бы предложил использовать более короткие псевдонимы, как здесь
Select Distinct p.Color AS [@Color]
, p.EnglishProductName AS [@EnglishProductName]
, A.Customizable as [@Customizable]
, sc.EnglishProductSubcategoryName AS [ProductSubCategory/@EnglishProductSubcategoryName]
From @Product as p
Inner Join @ProductSubCategory As sc On sc.ProductSubcategoryKey = p.ProductSubcategoryKey
CROSS JOIN (VALUES(1),(0)) A(Customizable)
For Xml PATH('Product');
Структура
Рано или поздно у вас появится продукт, который входит в состав нескольких подкатегорий.Я бы посоветовал спроектировать это как n:m
связанную систему с таблицей сопоставления между
Окончательный XML
Поскольку ваша подкатегория больше похожа на Семейство продуктов Вы можете создать что-то вроде
<ProductSubCategory EnglishProductSubcategoryName="Gloves">
<Product Color="Black" EnglishProductName="Full-Finger Gloves, L" Customizable="0" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, L" Customizable="1" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, M" Customizable="0" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, M" Customizable="1" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, S" Customizable="0" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, S" Customizable="1" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, L" Customizable="0" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, L" Customizable="1" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, M" Customizable="0" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, M" Customizable="1" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, S" Customizable="0" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, S" Customizable="1" />
<ProductSubCategory>
Или даже проще
<ProductSubCategory EnglishProductSubcategoryName="Gloves">
<Customizable value=1>
<Product Color="Black" EnglishProductName="Full-Finger Gloves, L" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, M" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, S" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, L" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, M" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, S" />
</Customizable>
<Customizable value=0>
<Product Color="Black" EnglishProductName="Full-Finger Gloves, L" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, M" />
<Product Color="Black" EnglishProductName="Full-Finger Gloves, S" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, L" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, M" />
<Product Color="Black" EnglishProductName="Half-Finger Gloves, S" />
</Customizable>
<ProductSubCategory>