Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Server - use Exists clause in Where and Select

I have a view that's something like

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)

The intent is to fetch all orders that have at least one line item of type 1 along with their current status.

We're in the process of adding a second type of line item, and I have modified the view such that it will include orders that have at least one line item of type 1 or type 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))

Easy enough, but I've just had a requirement added to show whether an order contains line items of type 1 or type 2 (or both) in the grid where these results are displayed:

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

The only way I can think of is to do:

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))

But this smells wrong with the duplication of the EXISTS clauses. Is there a better qway to write it? Can I make it perform better?

like image 286
Jon Avatar asked Jan 11 '11 09:01

Jon


People also ask

Can I use exists in select statement?

The operator returns the value as TRUE if the subquery contains any rows, otherwise FALSE. The exists operator can be used with either of these statements- SELECT, UPDATE, INSERT or DELETE.

WHERE do we use exist clause in select query?

The SQL EXISTS condition is used in combination with a subquery and is considered to be met, if the subquery returns at least one row. It can be used in a SELECT, INSERT, UPDATE, or DELETE statement.

Can we use exists in case statement in SQL?

Yes, just do: SELECT CASE WHEN EXISTS(subquery) THEN... There are some situations you can't use it (e.g. in a group by clause IIRC), but SQL should tell you quite clearly in that situation.

When to use exists and not exists?

Use EXISTS to identify the existence of a relationship without regard for the quantity. For example, EXISTS returns true if the subquery returns any rows, and [NOT] EXISTS returns true if the subquery returns no rows. The EXISTS condition is considered to be met if the subquery returns at least one row.


1 Answers

you can LEFT JOIN on OrderLineItemType1 and OrderLineItemType2 and then filter out rows where both of those columns are NULL in the WHERE clause.

like image 56
leeny Avatar answered Oct 05 '22 23:10

leeny