繁体   English   中英

SQL Server - 在Where和Select中使用Exists子句

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM