March 29, 2016 at 10:27 am
Hello Help forum,
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <=5
UNION
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001, 1002);
SELECT vend_id, prod_id, pro_price
FROM products
WHERE prod_price <=5
OR vend_id IN (1001, 1002);
My question, I am trying to create the same logic from the UNION using the 2 WHERE statements would I use the OR or AND operator?
March 29, 2016 at 10:31 am
You would use AND.
SELECT vend_id, prod_id, pro_price
FROM products
WHERE prod_price <=5
AND vend_id IN (1001, 1002);
-- Itzik Ben-Gan 2001
March 29, 2016 at 10:36 am
Alan.B (3/29/2016)
You would use AND.
SELECT vend_id, prod_id, pro_price
FROM products
WHERE prod_price <=5
AND vend_id IN (1001, 1002);
Disagree. This requires an OR.
select a from b where condition1
union (should probably be union all)
select a from b where condition2
is equivalent to
select a from b
where (condition1 or condition2)
The absence of evidence is not evidence of absence
- Martin Rees
The absence of consumable DDL, sample data and desired results is, however, evidence of the absence of my response
- Phil Parkin
March 29, 2016 at 10:40 am
Phil Parkin (3/29/2016)
Alan.B (3/29/2016)
You would use AND.
SELECT vend_id, prod_id, pro_price
FROM products
WHERE prod_price <=5
AND vend_id IN (1001, 1002);
Disagree. This requires an OR.
select a from b where condition1
union (should probably be union all)
select a from b where condition2
is equivalent to
select a from b
where (condition1 or condition2)
+1.
CREATE TABLE #products (vend_id int, prod_id int, prod_price money);
INSERT INTO #products VALUES
(1001,1,4),
(1002,2,6),
(1003,3,3),
(1004,4,6);
SELECT vend_id,
prod_id,
prod_price
FROM #products
WHERE prod_price<=5
UNION
SELECT vend_id,
prod_id,
prod_price
FROM #products
WHERE vend_id IN (1001,1002);
SELECT vend_id,
prod_id,
prod_price
FROM #products
WHERE prod_price<=5
AND
vend_id IN (1001,1002);
SELECT vend_id,
prod_id,
prod_price
FROM #products
WHERE prod_price<=5
OR
vend_id IN (1001,1002);
DROP TABLE #products;
Cheers!
EDIT: Fixed some alignment annoyances in the code snippet.
March 29, 2016 at 10:41 am
Phil Parkin (3/29/2016)
Alan.B (3/29/2016)
You would use AND.
SELECT vend_id, prod_id, pro_price
FROM products
WHERE prod_price <=5
AND vend_id IN (1001, 1002);
Disagree. This requires an OR.
select a from b where condition1
union (should probably be union all)
select a from b where condition2
is equivalent to
select a from b
where (condition1 or condition2)
Yep, NEC moment... I don't know what I was thinking.
-- Itzik Ben-Gan 2001
March 29, 2016 at 11:08 am
Phil Parkin (3/29/2016)
Alan.B (3/29/2016)
You would use AND.
SELECT vend_id, prod_id, pro_price
FROM products
WHERE prod_price <=5
AND vend_id IN (1001, 1002);
Disagree. This requires an OR.
select a from b where condition1
union (should probably be union all)
select a from b where condition2
is equivalent to
select a from b
where (condition1 or condition2)
Not necessarily.
SELECT a FROM b WHERE condition1
UNION ALL
SELECT a FROM b WHERE condition2
will create duplicates for records that meet both condition.
SELECT a FROM b
WHERE condition1 OR condition2
will retain duplicates, but not create duplicates where a record meets both conditions.
SELECT a
FROM b
WHERE condition1
UNION
SELECT a
FROM b
WHERE condition2
will eliminate all duplicates and is equivalent to
SELECT DISTINCT a
FROM b
WHERE condition1 OR condition2
Drew
J. Drew Allen
Business Intelligence Analyst
Philadelphia, PA
March 29, 2016 at 11:45 am
Quick thought, the first (union) query will use two index seek operators (if the correct indices are in place) while the latter does a single scan. If the cardinality of the table is low this probably doesn't matter but if it high then the difference can be huge.
😎
Further, by changing the UNION to UNION ALL and use a CTE to select distinct value the optimizer will remove the distinct sort operator.
;WITH BASE_DATA AS
(
SELECT
vend_id
,prod_id
,prod_price
FROM products
WHERE prod_price <=5
UNION ALL
SELECT
vend_id
,prod_id
,prod_price
FROM products
WHERE vend_id IN (1001, 1002)
)
SELECT DISTINCT
BD.vend_id
,BD.prod_id
,BD.prod_price
FROM BASE_DATA BD;
March 29, 2016 at 12:21 pm
I thought it would need the AND operator because you need a price filter and then the vender check. But I see that the UNION is joining 2 separate tables so the OR would be used. Since it is checking the first statement if it is TRUE and then checking the 2nd statement if it is TRUE. Is this the correct logic?
March 29, 2016 at 2:15 pm
Eirikur Eiriksson (3/29/2016)
Quick thought, the first (union) query will use two index seek operators (if the correct indices are in place) while the latter does a single scan. If the cardinality of the table is low this probably doesn't matter but if it high then the difference can be huge.😎
Further, by changing the UNION to UNION ALL and use a CTE to select distinct value the optimizer will remove the distinct sort operator.
;WITH BASE_DATA AS
(
SELECT
vend_id
,prod_id
,prod_price
FROM products
WHERE prod_price <=5
UNION ALL
SELECT
vend_id
,prod_id
,prod_price
FROM products
WHERE vend_id IN (1001, 1002)
)
SELECT DISTINCT
BD.vend_id
,BD.prod_id
,BD.prod_price
FROM BASE_DATA BD;
Even more efficient (and in my opinion easier to udnerstand):
SELECT
vend_id
,prod_id
,prod_price
FROM products
WHERE prod_price <=5
UNION ALL
SELECT
vend_id
,prod_id
,prod_price
FROM products
WHERE vend_id IN (1001, 1002)
AND prod_price > 5; -- Exclude rows from first query to prevent duplicates
Note that if prod_price is nullable, you will have to change the last line to either "AND (prod_price > 5 OR prod_price IS NULL)", or to "AND COALESCE(prod_price, 9) > 5"
March 29, 2016 at 3:32 pm
Hugo Kornelis (3/29/2016)
Eirikur Eiriksson (3/29/2016)
Quick thought, the first (union) query will use two index seek operators (if the correct indices are in place) while the latter does a single scan. If the cardinality of the table is low this probably doesn't matter but if it high then the difference can be huge.😎
Further, by changing the UNION to UNION ALL and use a CTE to select distinct value the optimizer will remove the distinct sort operator.
;WITH BASE_DATA AS
(
SELECT
vend_id
,prod_id
,prod_price
FROM products
WHERE prod_price <=5
UNION ALL
SELECT
vend_id
,prod_id
,prod_price
FROM products
WHERE vend_id IN (1001, 1002)
)
SELECT DISTINCT
BD.vend_id
,BD.prod_id
,BD.prod_price
FROM BASE_DATA BD;
Even more efficient (and in my opinion easier to udnerstand):
SELECT
vend_id
,prod_id
,prod_price
FROM products
WHERE prod_price <=5
UNION ALL
SELECT
vend_id
,prod_id
,prod_price
FROM products
WHERE vend_id IN (1001, 1002)
AND prod_price > 5; -- Exclude rows from first query to prevent duplicates
Note that if prod_price is nullable, you will have to change the last line to either "AND (prod_price > 5 OR prod_price IS NULL)", or to "AND COALESCE(prod_price, 9) > 5"
Very nice Hugo,
two index seeks and concatenation eliminating the costly Hash Match Aggregate, brilliant!
😎
Viewing 10 posts - 1 through 9 (of 9 total)
You must be logged in to reply to this topic. Login to reply