我想在我的Orders表中更新一个标志值,但前提是我的OrderItems表中的OrderID连接到Orders记录的至少一个OrderItem是某种状态。
场景1:连接到订单的所有3个OrderItem都是“已取消” - 不更新订单标记
场景2:连接到订单的至少一个OrderItem未被“取消” - 更新订单标志
场景3:连接到订单的OrderItem都没有被“取消” - 更新订单标志
如何做到这一点 - 并且有效率?
这就是我所拥有的:
UPDATE o
SET o.Flag = true
FROM Orders o
INNER JOIN OrderItems oi ON oi.OrderID = o.OrderID
WHERE o.Flag = false
AND oi.State <> 'Cancelled'
INNER JOIN可能会从OrderItems返回多条记录。不确定这是不是一个问题。
答案 0 :(得分:1)
这样的事情:
create table orders
(
orderID int,
orderName varchar(50),
orderDate datetime,
isValidOrderFlag bit
)
create table orderdetail
(
orderdetailID int,
orderID int,
productName varchar(100),
productCost numeric(9,2),
quantity int,
isCancelled bit
)
insert into orders values (1234, 'Bob Garvey', GETDATE() - 5, 0);
insert into orders values (1235, 'Susan Hamilton', GETDATE() - 5, 0);
insert into orders values (1236, 'Bob Garvey', GETDATE() - 5, 0);
insert into orders values (1237, 'Sarah Smith', GETDATE() - 4, 0);
-- all 3 order items are cancelled do not update orders flag
insert into orderdetail values (10000, 1234, 'thing1', 9.95, 10, 1);
insert into orderdetail values (10001, 1234, 'thing2', 5.99, 10, 1);
insert into orderdetail values (10002, 1234, 'thing3', 1.99, 1, 1);
-- at least one order is cancelled update orders flag
insert into orderdetail values (10000, 1235, 'thing1', 9.95, 10, 1);
insert into orderdetail values (10001, 1235, 'thing2', 5.99, 10, 0);
insert into orderdetail values (10002, 1235, 'thing3', 1.99, 1, 0);
-- at least one order is cancelled update orders flag
insert into orderdetail values (10000, 1236, 'thing1', 9.95, 10, 1);
insert into orderdetail values (10001, 1236, 'thing2', 5.99, 10, 1);
insert into orderdetail values (10002, 1236, 'thing3', 1.99, 1, 0);
-- no orders are cancelled dupdate orders flag
insert into orderdetail values (10000, 1237, 'thing1', 9.95, 10, 0);
insert into orderdetail values (10001, 1237, 'thing2', 5.99, 10, 0);
insert into orderdetail values (10002, 1237, 'thing3', 1.99, 1, 0);
select orderid, max(iscancelled)
from orderdetail
group by orderid
--count detail items
update o
set isvalidorderflag = 1
from
dbo.orders o
join
(
select orderid
, count(*) [total_lines]
, sum(case when iscancelled = 1 then 1 else 0 end) [total]
from orderdetail
group by orderid) main on main.orderid = o.orderid
where
main.total_lines <> main.total
答案 1 :(得分:1)
基本上,必需语句应仅针对方案2和3更新dbo.Orders
表中的行。
1)如果 - 对于S2和S3 - 您必须使用相同的标志更新订单,一个解决方案正在跟随更新:
UPDATE o
SET Flag = 1 -- common flag for S2 and S3
FROM dbo.Orders o
WHEER EXISTS (
SELECT * FROM dbo.OrderItems oi
WHERE oi.OrderID = o.OrderID
-- Uncomment if oi.Status allows NULLs
AND (/*oi.Status IS NULL OR*/ oi.Status <> 'Cancelled')
)
2)如果你需要更新到差异,请使用Buf。 flags然后我将使用以下语句
UPDATE o
SET Flag =
CASE
WHEN EXISTS(SELECT * FROM dbo.OrderItems oi2 WHERE oi2.OrderID = o.OrderID AND oi2.Status = 'Cancelled')
THEN 2 -- Status for second scenario
ELSE 3 -- Status for third scenario
END
FROM dbo.Orders o
WHEER EXISTS (
SELECT * FROM dbo.OrderItems oi
WHERE oi.OrderID = o.OrderID
-- Uncomment if oi.Status allows NULLs
AND (/*oi.Status IS NULL OR*/ oi.Status <> 'Cancelled')
)
答案 2 :(得分:0)
看起来您需要OrderItems
表上的DML触发器,它将更新Order
状态,与orderItems的更改方式无关。
更新版本
create trigger tr_OrderItems
on dbo.OrderItems after insert, update, delete
as
begin
set nocount on
declare @orders table(orderId int)
insert @orders(orderid)
select orderid from inserted
union --distinct
select orderid from deleted
--update orders
;with items as (--calculate counts
select oi.orderid, count(*) itemCnt,
count(case status when 'Cancelled' then 1 end) cancelledCnt
--not 'Cancelled' produce null and not counted
from dbo.OrderItems oi
inner join @orders o on o.orderid = oi.orderid
group by oi.orderid
)--CTE
update orders
set flag = case when i.itemCnt = i.cancelledCnt then 'AllCancelled'
when i.cancelledCnt = 0 then 'NoneCancelled'
else 'SomeCancelled' end
from orders o
inner join items i on o.orderid = i.orderid
end