2009-08-30 9 views
0

У меня есть MS SQL Server с базой данных для магазина электронной коммерции.SQL сделать строки в столбцы, PIVOT возможно

Это некоторые из таблиц у меня есть:

Products: 
Id | Name | Price 

ProductAttributeTypes: -Color, Size, Format 
Id | Name 

ProductAttributes: --Red, Green, 12x20 cm, Mirrored 
Id | ProductAttributeTypeId | Name 

Orders: 
Id | DateCreated 

OrderItems: 
Id | OrderId | ProductId 

OrderItemsToProductAttributes: --Relates an OrderItem to its product and selected attributes 
OrderItemId | ProductAttributeId | ProductAttributeTypeId | ProductId 

Я хочу, чтобы выбрать из таблицы ТоварыЗаказа, чтобы увидеть, какие предметы были приобретены.

Чтобы узнать, какие варианты (ProductAtriibutes) были выбраны, я хочу, чтобы они были «динамическими» столбцами в наборе результатов.

Так ResultSet должен выглядеть следующим образом:

OrderItemId | ProductId | ProductName | Color | Size | Format 
     1234   123 Mount. Bike Red  2x20 Mirror 

Я не знаю, если PIVOT является вещь, чтобы использовать? Я не использую какие-либо агрегированные функции, поэтому я думаю, что нет ...

Есть ли какие-нибудь SQL-ниндзя, которые могут мне помочь?

ответ

1

Если вы используете sql2005 или 2008, вы можете использовать команду поворота. См here.

В примере ниже OrderAttributes набор будет выглядеть следующим образом:

OrderItemId AttName AttValue 
     ----- ------ ----- 
     100 Color Red 
     100 Size Small 
     101 Color Blue 
     101 Size Small 
     102 Color Red 
     102 Size Small 
     103 Color Blue 
     103 Size Large 

Окончательные результаты после PIVOT будут:

OrderItemId Size Color 
    ----- ------ ----- 
    100 Small Red 
    101 Small Blue 
    102 Small Red 
    103 Large Blue 

WITH OrderAttributes(OrderItemId, AttName, AttValue) 
    AS (
     SELECT 
     OrderItemId, 
     pat.Name AS AttName, 
     pa.Name AS AttValue 
     FROM OrderItemsToProductAttributes x 
     INNER JOIN ProductAttributes pa 
     ON x.ProductAttributeId = pa.id 
     INNER JOIN ProductAttributeTypes pat 
     ON pa.ProductAttributeTypeId = pat.Id 
    ) 

SELECT AttrPivot.OrderItemId, 
[Size] AS [Size], 
[Color] AS Color 
FROM OrderAttributes 
PIVOT ( 
     MAX([AttValue]) 
     FOR [AttName] IN ([Color],[Size]) 
    ) AS AttrPivot 
ORDER BY AttrPivot.OrderItemId 

Существует способ динамического построения столбцов (т.е. столбцы «Цвет и размер»), как можно видеть. here. Убедитесь, что уровень совместимости вашей базы данных в вашей базе данных установлен на то, что превышает 2000, или вы получите странные ошибки.

+0

Как? Когда я не использую какие-либо агрегированные функции? Я не хочу подытоживать идентификаторы или что-то в этом роде. – MartinHN

+0

Я думаю, что сейчас это очень близко, но значение столбцов «Цвет и размер» равно null. Может быть, просто небольшая деталь отсутствует? – MartinHN

+0

Одна вещь может вызвать diff, у вас был ProductAttributeTypeId в таблице OrderItemsToProductAttributes, я не поместил это в свой пример b/c, на который следует ссылаться через соединения (третья нормальная форма и все). Если вы говорите, что они могут иметь нули, то что-то должно быть изменено на что-то вроде: SELECT AttrPivot.OrderItemId, isnull ([Размер], 'NA') AS [Размер], isnull ([Цвет], 'NA ') AS Color FROM OrderAttributes – JBrooks

0

В прошлом я создал физические таблицы только для чтения. Структура, которую вы имеете выше, GREAT для хранения, но ужасно для отчетности.

Таким образом, вы можете сделать следующее: Написать скрипт (который запланирован ночной) или триггер (изменение данных), который выполняет следующие задачи:

во-первых, вы должны динамически пройти через каждый продукт и строить статическая таблица «Product_ [ProductName]»

Затем пройдите через каждый ProductAttributeTypes для каждого продукта и создайте/обновите/удалите физический столбец в соответствующей таблице Product.

Затем заполнить эту таблицу с соответствующими значениями на основе OrderItemsToProductAttributes и ProductAttributes

Это просто грубая идея. Убедитесь, что вы храните OrderID в таблицах «Static»/«Flattened». И убедитесь, что вы делаете все остальное, что вам нужно. Но после этого вы сможете начать вытягивать из этих сплющенных таблиц, чтобы получить нужные вам данные.

+0

Я получаю вашу точку зрения. Я согласен с тем, что дизайн базы данных для хранения и отчетности имеет свои конфликты и ограничения. Но я не думаю, что этот запрос достаточно велик, чтобы использовать агрегированные таблицы, поскольку он дает мне другие проблемы, такие как избыточность, задержки в обновлениях и т. Д. – MartinHN

0

Pivot является лучшим выбором, но то, что я сделал для целей отчетности, и сделать это хорошо работать с SSIS, чтобы создать представление, которое затем этот запрос:

SELECT  [InputSetID], [InputSetName], CAST([470] AS int) AS [Created By], CAST([480] AS datetime) AS [Created], CAST([479] AS int) AS [Updated By], CAST([460] AS datetime) 
         AS [Updated] 
FROM   (SELECT  st.InputSetID, st.InputSetName, avt.InputSetID AS avtID, avt.AttributeID, avt.Value 
         FROM   app.InputSetAttributeValue avt JOIN 
               app.InputSets st ON avt.InputSetID = st.InputSetID) AS p PIVOT (MAX(Value) FOR AttributeID IN ([470], [480], [479], [460])) AS pvt 

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

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