考虑以下表格:
产品
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
矩阵允许为单个产品分配多个类别(典型的多对多关系)。例如, Pen 属于两个类别, Office 和 Home 。我希望创建此数据的可编辑视图,如下所示:
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。如果没有,无论如何,我们将等待:)
答案 0 :(得分:2)
任何视图都可以使用INSTEAD OF触发器进行更新。
http://msdn.microsoft.com/en-us/library/ms187956.aspx
在您的情况下,SQL Server无法自动使其可更新,但您可以将列映射到触发器中的行。
看看这些页面:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=120679
SQL pivoted table is read-only and cells can't be edited?
可以从中得出一个观点:
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;
对此进行触发将涉及相当多的代码,但并不是非常困难。
答案 1 :(得分:0)
这在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