我有一个类似
的观点CREATE VIEW OrdersView WITH SCHEMABINDING AS
SELECT o.Id, o.OrderDate, o.LastName, o.TotalPrice, s.Status
FROM dbo.Orders o INNER JOIN dbo.OrderStatus s on o.Id = s.OrderId
WHERE NOT EXISTS (SELECT NULL from dbo.OrderStatus where OrderId = s.OrderId and StatusDate > s.StatusDate
AND EXISTS (SELECT NULL FROM dbo.OrderLineItemType1 WHERE OrderId = o.Id)
目的是获取至少有一个类型1的订单项及其当前状态的所有订单。
我们正在添加第二种订单项,我修改了该视图,使其包含至少包含一个类型1或类型2的订单项的订单:
CREATE VIEW OrdersView WITH SCHEMABINDING AS
SELECT o.Id, o.OrderDate, o.LastName, o.TotalPrice, s.Status
FROM dbo.Orders o INNER JOIN dbo.OrderStatus s on o.Id = s.OrderId
WHERE NOT EXISTS (SELECT NULL from dbo.OrderStatus where OrderId = s.OrderId and StatusDate > s.StatusDate
AND (EXISTS (SELECT NULL FROM dbo.OrderLineItemType1 WHERE OrderId = o.Id)
OR EXISTS (SELECT NULL FROM dbo.OrderLineItemType2 WHERE OrderId = o.Id))
很简单,但我刚刚添加了一项要求,以显示订单是否包含显示这些结果的网格中类型1或类型2(或两者)的订单项:
Order ID | T1 | T2 | Last name | Price | Status ============================================================ 12345 | x | | Smith | $100.00 | In Production 12346 | x | x | Jones | $147.23 | Part Dispatched 12347 | | x | Atwood | $12.50 | Dispatched
我能想到的唯一方法就是:
CREATE VIEW OrdersView WITH SCHEMABINDING AS
SELECT o.Id,
CASE WHEN EXISTS (SELECT NULL FROM dbo.OrderLineItemType1 WHERE OrderID = o.Id) THEN 1 ELSE 0 END AS HasType1,
CASE WHEN EXISTS (SELECT NULL FROM dbo.OrderLineItemType2 WHERE OrderId = o.ID) THEN 1 ELSE 0 END AS HasType2,
o.OrderDate, o.LastName, o.TotalPrice, s.Status
FROM dbo.Orders o INNER JOIN dbo.OrderStatus s on o.Id = s.OrderId
WHERE NOT EXISTS (SELECT NULL from dbo.OrderStatus where OrderId = s.OrderId and StatusDate > s.StatusDate
AND (EXISTS (SELECT NULL FROM dbo.OrderLineItemType1 WHERE OrderId = o.Id)
OR EXISTS (SELECT NULL FROM dbo.OrderLineItemType2 WHERE OrderId = o.Id))
但这与EXISTS
条款的重复有些不一致。写一个更好的qway吗?我可以让它表现更好吗?
答案 0 :(得分:3)
您可以在OrderLineItemType1和OrderLineItemType2上LEFT JOIN,然后在WHERE子句中过滤掉这两列都为NULL的行。
答案 1 :(得分:0)
可能值得分析的一个变化(但与您的具体问题没有直接关系)。
以下两行:
FROM dbo.Orders o INNER JOIN dbo.OrderStatus s on o.Id = s.OrderId
WHERE NOT EXISTS (SELECT NULL from dbo.OrderStatus where OrderId = s.OrderId and StatusDate > s.StatusDate
最好将其写为:
FROM dbo.Orders o INNER JOIN dbo.OrderStatus s on o.Id = s.OrderId
LEFT JOIN dbo.OrderStatus s_later on o.Id = s_later.OrderId and s_later.StatusDate > s.StatusDate
WHERE s_later.OrderId is null
我通常发现这表现得更好(但这是值得分析两种方式之一)。
LEFT JOIN尝试查找适用于同一订单的后续行,然后WHERE子句拒绝发生此类匹配的任何潜在结果行 - 因此s中唯一匹配的行必须是此订单的最新行。 / p>
答案 2 :(得分:0)
您根本不需要EXISTS
:
SELECT o.Id, HasType1, HasType2, o.OrderDate, o.LastName, o.TotalPrice, s.Status
FROM dbo.Orders o
CROSS APPLY
(
SELECT TOP 1 s.*
FROM dbo.OrderStatus
WHERE OrderId = o.Id
ORDER BY
StatusDate DESC
) s
OUTER APPLY
(
SELECT TOP 1 1 AS HasType1
FROM dbo.OrderLineItemType1
WHERE OrderID = o.Id
) olt1
OUTER APPLY
(
SELECT TOP 1 1 AS HasType2
FROM dbo.OrderLineItemType2
WHERE OrderID = o.Id
) olt2