Можно ли создать редактируемый вид чемпионата «многие ко многим»? - PullRequest
1 голос
/ 14 марта 2012

Рассмотрим следующие таблицы:

Продукты

ID | Name | etc
1  | Pen  | wtv
2  | Pad  | wtv
3  | Ball | wtv
...| ...  | ...
thousands of products

Категории

ID | Name   | etc
1  | Office | wtv
2  | Home   | wtv
3  | Park   | wtv
...| ...    | ...
hundreds of categories

productCategoryMatrix

ProductID | CategoryID
1         | 1
1         | 2
2         | 1
2         | 2
2         | 3
3         | 3
... et cetera

Матрица позволяет назначать несколько категорий одному продукту (типичное соотношение «многие ко многим»).Например, Ручка относится к двум категориям: Офис и Дом .Я хочу создать редактируемое представление этих данных, которое будет выглядеть следующим образом:

ProductsWithCategories

ProductID | ProductName | Category | Category | Category | Category | Category
1         | Pen         | 1        | 2        |          |          |
2         | Pad         | 1        | 2        | 3        |          |
3         | Ball        | 3        |          |          |          |
          |               ... Thousands of products ...             |

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

Можно ли создать такой вид с помощью SQL Server 2008 R2?Если ваши решения также работают с SQL Server 2000, это было бы замечательно, поскольку мы перейдем на 2008 год только через три недели.Если нет, то неважно, будем ждать :)

Ответы [ 2 ]

2 голосов
/ 15 марта 2012

Любое представление можно сделать обновляемым с помощью триггера INSTEAD OF.

http://msdn.microsoft.com/en-us/library/ms187956.aspx

В вашем случае SQL Server не может автоматически сделать его обновляемым, но вы можете сопоставить столбцы со строками в вашем триггере.

Посмотрите на эти страницы:

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=120679

Сводная таблица SQL доступна только для чтения, и ячейки нельзя редактировать?

Из этого можно сделать вид:

DECLARE @Products TABLE (ID INT, Name VARCHAR(50));
DECLARE @Categories AS TABLE (ID INT, Name VARCHAR(50));
DECLARE @ProductCategoryMatrix AS TABLE (ProductID INT, CategoryID INT);

INSERT INTO @Products (ID, Name) VALUES (1, 'Pen'), (2, 'Pad'), (3, 'Ball');
INSERT INTO @Categories VALUES (1, 'Office'), (2, 'Home'), (3, 'Work');
INSERT INTO @ProductCategoryMatrix VALUES (1, 1), (1, 2), (2, 1), (2, 2), (2, 3), (3, 3);

-- CREATE VIEW AS -- (change variables to real tables)
WITH CategoriesOrdered AS (
    SELECT p.ID AS ProductID
           ,'Cat' + CAST(ROW_NUMBER() OVER(PARTITION BY pc.ProductID ORDER BY pc.CategoryID) AS VARCHAR(1)) AS CategoryColumn
           ,pc.CategoryID
    FROM @Products p
    INNER JOIN @ProductCategoryMatrix pc
        ON pc.ProductID = p.ID
)
,CategoriesFlat AS (
    SELECT *
    FROM CategoriesOrdered
    PIVOT (MIN(CategoryID) FOR CategoryColumn IN ([Cat1], [Cat2], [Cat3], [Cat4], [Cat5])) AS pvt
)
,ProductsWithCategories AS (
    SELECT *
    FROM @Products p
    LEFT JOIN CategoriesFlat cf
        ON cf.ProductID = p.ID
)
SELECT *
FROM ProductsWithCategories;

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

0 голосов
/ 16 марта 2012

это прекрасно работает на sql 2k, я тестировал

select 
p.ID, 
p.Name,
c1.cid     as cat1,
c2.cid     as cat2,
c3.cid     as cat3,
c4.cid     as cat4,
c5.cid     as cat5
from 
Products p
inner join                    --  use left join if you want to have listed products with any category
   (select pcm1.ProductID, min(pcm1.CategoryID) as cid
    from productCategoryMatrix pcm1 group by ProductID) as c1 on p.ID = c1.productID

left join
   (select pcm1.productID, min(pcm2.CategoryID) as cid
    from      productCategoryMatrix pcm1
    left join productCategoryMatrix pcm2 on pcm1.productID = pcm2.productID and pcm1.CategoryID < pcm2.CategoryID
    group by pcm1.ProductID
   ) as c2 on p.ID = c2.productID

left join
   (select pcm1.productID, min(pcm3.CategoryID) as cid
    from      productCategoryMatrix pcm1
    left join productCategoryMatrix pcm2 on pcm1.productID = pcm2.productID and pcm1.CategoryID < pcm2.CategoryID
    left join productCategoryMatrix pcm3 on pcm1.productID = pcm3.productID and pcm2.CategoryID < pcm3.CategoryID
    group by pcm1.ProductID
   ) as c3 on p.ID = c3.productID

left join
   (select pcm1.productID, min(pcm4.CategoryID) as cid
    from      productCategoryMatrix pcm1
    left join productCategoryMatrix pcm2 on pcm1.productID = pcm2.productID and pcm1.CategoryID < pcm2.CategoryID
    left join productCategoryMatrix pcm3 on pcm1.productID = pcm3.productID and pcm2.CategoryID < pcm3.CategoryID
    left join productCategoryMatrix pcm4 on pcm1.productID = pcm4.productID and pcm3.CategoryID < pcm4.CategoryID
    group by pcm1.ProductID
   ) as c4 on p.ID = c4.productID

left join
   (select pcm1.productID, min(pcm5.CategoryID) as cid
    from      productCategoryMatrix pcm1
    left join productCategoryMatrix pcm2 on pcm1.productID = pcm2.productID and pcm1.CategoryID < pcm2.CategoryID
    left join productCategoryMatrix pcm3 on pcm1.productID = pcm3.productID and pcm2.CategoryID < pcm3.CategoryID
    left join productCategoryMatrix pcm4 on pcm1.productID = pcm4.productID and pcm3.CategoryID < pcm4.CategoryID
    left join productCategoryMatrix pcm5 on pcm1.productID = pcm5.productID and pcm4.CategoryID < pcm5.CategoryID
    group by pcm1.ProductID
   ) as c5 on p.ID = c5.productID
...