我有一张桌子"订单"像这样,它包含有关订单的信息。
Order ID | ... | Order Total
然而,订单包括几个项目,还有一个"项目订单"表:
Item Order ID | Order ID | Item ID
" Item"表:
Item ID | Cost
因此,订单< - >项目订单具有一对多关系,并且项目订单< - >物品有多对一的关系。
逻辑上,订单总额应取决于其中每个商品订单的成本,这会将商品的成本添加到总计。
如何设置依赖关系,订单总额取决于与此订单对应的所有项目订单,并总结所有需要的项目成本?我想每次在订单中添加新的商品订单时也应该更新。
答案 0 :(得分:1)
如评论中所示,我通常不希望存储冗余的,可能不正确的数据。但是,如果在运行中计算总数存在性能问题,则下一个最佳选择是让系统为您进行计算。如果您使用索引视图,则可以选择此选项。
表格设置:
create table dbo.Orders (
OrderID int not null,
/* NO Total here */
constraint PK_Orders PRIMARY KEY (OrderID)
)
go
create table dbo.Items (
ItemID int not null,
Cost decimal (19,4) not null,
constraint PK_Items PRIMARY KEY (ItemID)
)
go
create table dbo.OrderItems (
OrderItemID int not null,
OrderID int not null,
ItemID int not null,
/* I'd normally prefer Order/Item/Quantity and making Order/Item the PK */
constraint PK_OrderItems PRIMARY KEY (OrderItemID),
constraint FK_OrderItems_Orders FOREIGN KEY (OrderID) references Orders (OrderID),
constraint FK_OrderItems_Items FOREIGN KEY (ItemID) references Items (ItemID)
)
现在我们可以创建视图了:
create view dbo.OrderTotals
with schemabinding
as
select
OrderID,
COUNT_BIG(*) as LineCount, /* Required for indexed view with aggregate */
SUM(Cost) as OrderTotal
from
dbo.Items i
inner join
dbo.OrderItems o
on
i.ItemID = o.ItemID
group by
OrderID
go
create unique clustered index IX_OrderTotals on OrderTotals (OrderID)
现在,当您对OrderItems或Items表执行插入,更新和删除时,此视图的索引(实际上包含所有视图数据)会自动为您更新。
这可以避免任何关于角落情况的担忧,如果您使用例如触发器手动执行更新。
答案 1 :(得分:0)
您可以在Item Order
和Item
表格上创建两个触发器。
触发Item
表:
CREATE TRIGGER T_Item_Recalc_Order_Total
ON Item
FOR DELETE, INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
UPDATE o
SET [Order Total] = c.[Cost]
FROM Order o
INNER JOIN
(
SELECT i_o.[Order_ID]
,SUM(Cost) AS Cost
FROM Item_Order i_o
INNER JOIN Item i
ON i.[Item ID] = i_o.[Item ID]
WHERE i_o.[Item ID] IN (
-- Sum up cost for changed rows only
SELECT COALESCE(d.[Item ID], i.[Item ID]) AS [Item ID]
FROM deleted d
FULL OUTER JOIN inserted i
ON d.[Item ID] = i.[Item ID]
WHERE d.[Item ID] IS NULL OR i.[Item ID] IS NULL OR d.[Cost] <> i.[Cost]
)
GROUP BY i_o.[Order_ID]
) c
ON o.[Order_ID] = c.[Order_ID]
END
触发Item Order
表:
CREATE TRIGGER T_Item_Order_Recalc_Order_Total
ON Item_Order
FOR DELETE, INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
UPDATE o
SET [Order Total] = c.[Cost]
FROM Order o
INNER JOIN
(
SELECT i_o.[Order_ID]
,SUM(Cost) AS Cost
FROM Item_Order i_o
INNER JOIN Item i
ON i.[Item ID] = i_o.[Item ID]
WHERE i_o.[Order_ID] IN (
-- Sum up cost for changed rows only
SELECT deleted.[Order_ID]
UNION
SELECT inserted.[Order_ID]
)
GROUP BY i_o.[Order_ID]
) c
ON o.[Order_ID] = c.[Order_ID]
END