[英]SQL Server - use Exists clause in Where and Select
我有一个类似的观点
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
条款的重复EXISTS
不一致。 写一个更好的qway吗? 我可以让它表现更好吗?
您可以在OrderLineItemType1和OrderLineItemType2上LEFT JOIN,然后过滤掉WHERE子句中这两列都为NULL的行。
一个可能值得分析的变化(但与您的具体问题没有直接关系)。
以下两行:
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中唯一匹配的行必须是此订单的最新行。
你根本不需要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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.