Reputation: 27
I have a table Product with the following columns:
id | product_name | price
1 | Red Shirt | 10.0
2 | White Shirt | 15.0
3 | Black Shirt | 9.0
4 | Yellow Shirt | 12.0
How could I make a query that would return the rows that have max(price) and min(price)? Using the example above the output should be:
id | product_name | price
3 | Black Shirt | 9.0
2 | White Shirt | 15.0
In case of repeated values, it doesn't matter which one is selected, as long the output is just 2 rows.
Upvotes: 1
Views: 242
Reputation: 167867
You can do it using the ROW_NUMBER()
analytic function which only uses a single table scan (unlike solutions that use UNION
or sub-queries).
Oracle Setup:
CREATE TABLE product ( id, product_name, price ) AS
SELECT 1, 'Red Shirt', 10.0 FROM DUAL UNION ALL
SELECT 2, 'White Shirt', 15.0 FROM DUAL UNION ALL
SELECT 3, 'Black Shirt', 9.0 FROM DUAL UNION ALL
SELECT 4, 'Yellow Shirt', 12.0 FROM DUAL UNION ALL
SELECT 5, 'Blue Shirt', 9.0 FROM DUAL
Query:
SELECT id, product_name, price
FROM (
SELECT p.*,
ROW_NUMBER() OVER ( ORDER BY price ASC ) As min_price_rn,
ROW_NUMBER() OVER ( ORDER BY price DESC ) As max_price_rn
FROM product p
)
WHERE min_price_rn = 1
OR max_price_rn = 1;
Output:
ID | PRODUCT_NAME | PRICE -: | :----------- | ----: 2 | White Shirt | 15 3 | Black Shirt | 9
db<>fiddle here
Upvotes: 2
Reputation: 1790
A couple of the other answers do not cater for the last requirement... 'In case of repeated values, it doesn't matter which one is selected, as long the output is just 2 rows.'
They will return three rows if there is two products with the same value.
the below gets around that by adding the rownum = 1 clause.
with testtab (id, product_name, price) as
(select 1, 'Red Shrit', 10.00 from dual
union
select 2, 'Whtie Shrit', 15.00 from dual
union
select 3, 'Black Shrit', 9.00 from dual
union
select 4, 'Yellow Shrit', 12.00 from dual
union
select 4, 'Pink Shrit', 15.00 from dual)
select id, product_name, price
from testtab
where price in (select max(price) from testtab)
and rownum = 1
union
select id, product_name, price
from testtab where price in (select min(price) from testtab)
and rownum = 1
Upvotes: 2
Reputation: 6522
You can do this as well:
select *
from product
where price in (
(select min(price) from product),
(select max(price) from product)
);
Or you can do union like below:
-- The UNION approach
Select *
from Product
where price = (select min(price) from Product)
union
select *
from Product
where price = (select max(price) from Product);
Used the following:
Create Table Product(id int, product_name varchar(20), price decimal);
Insert into Product values (1, 'Red Shirt', 10.0);
Insert into Product values (2, 'White Shirt', 15.0);
Insert into Product values (3, 'Black Shirt', 9.0);
Insert into Product values (4, 'Yellow Shirt', 12.0);
Select *
from Product
where Price in (
(select min(Price) from Product),
(select max(Price) from Product)
);
Final Output:
Id Product_Name Price
2 White Shirt 15
3 Black Shirt 9
Upvotes: 0
Reputation: 1845
You can make use of Or condition in your where condition.
with cte as (select 1 as ID, 'Red Shirt' as Product_name, 10.0 as price from dual
union all
select 2 as ID, 'White Shirt' as Product_name, 15.0 as price from dual
union all
select 3 as ID, 'Black Shirt' as Product_name, 9.0 as price from dual
union all
select 4 as ID, 'Yellow Shirt' as Product_name, 12.0 as price from dual )
select * from cte
where price = (select min(price) minprice from cte) or price = (select max(price)
maxprice from cte);
Output:
ID PRODUCT_NAME PRICE
2 White Shirt 15
3 Black Shirt 9
Upvotes: 0