I have a table Sales with the following fields: code, amount, index, name.
I need to get the smallest and the largest amount for a given name, and the code for which the amount is the smallest and largest.
Can somebody help me in constructing a query?
If CTE and row_number() is available to you.
with S as
(
select Amount,
Code,
row_number() over(order by Amount asc) as rn1,
row_number() over(order by Amount desc) as rn2
from Sales
where Name = 'SomeName'
)
select SMin.Amount as MinAmount,
SMin.Code as MinCode,
SMax.Amount as MaxAmount,
SMax.Code as MaxCode
from S as SMin
cross join S as SMax
where SMin.rn1 = 1 and
SMax.rn2 = 1
To find min and max amount per name:
select
name
min(amount), max(amount)
from
sales
group by name
and to get both(min and max) and code in single query:
select *
from sales s
where
(amount = (select
max(s1.amount)
from sales s1
where s1.name = s.name)
or
amount = (select
min(s2.amount)
from sales s2
where s2.name = s.name)
)
Assuming this is Postgres, try the following:
select name,
amount,
code,
case when min_rank=max_rank then 'Minimum and Maximum'
when min_rank=1 then 'Minimum'
else 'Maximum'
end as min_or_max
from
(select s.*,
rank() over (partition by name order by amount) min_rank,
rank() over (partition by name order by amount desc) max_rank
from sales s) v
where 1 in (min_rank, max_rank)
Related
Most Expensive And Cheapest Wine
I'm trying to solve this question from Stratascratch, following the hint was given on the platform.
Find the cheapest and the most expensive variety in each region. Output the region along with the corresponding most expensive and the cheapest variety.
Please help review my answer and would love to know the better way to solve this.
SELECT EX.region_1, EX.expensive_variety, CH.cheap_variety
FROM
(SELECT A.region_1, A.expensive_variety
FROM
(SELECT distinct region_1, variety AS expensive_variety, price,
ROW_NUMBER() OVER (PARTITION BY region_1 ORDER BY price desc) as
most_expensive
FROM winemag_p1
ORDER BY region_1 asc) A
WHERE A.most_expensive = 1) EX
INNER JOIN
(SELECT B.region_1, B.cheap_variety
FROM
(SELECT distinct region_1, variety as cheap_variety, price,
ROW_NUMBER() OVER (PARTITION BY region_1 ORDER BY price ASC) as cheapest
FROM winemag_p1
ORDER BY region_1 asc) B
WHERE B.cheapest = 1) CH
ON EX.region_1 = CH.region_1
Something like this, the MIN and MAX per region:
SELECT region
, MIN(price) AS cheapest
, MAX(price) AS most_expensive
FROM table_name
GROUP BY region;
You can find both in the same sub-query.
SELECT
B.region_1,
MAX(CASE WHEN cheapest = 1 then variety else '' end) cheapest_variety,
MAX(CASE WHEN cheapest = 1 then price else 0 end) cheapest_price,
MAX(CASE WHEN expensive = 1 then variety else '' end) expensive_variety,
MAX(CASE WHEN expensive = 1 then price else 0 end) expensive_price
FROM
(SELECT distinct region_1, variety as cheap_variety, price,
ROW_NUMBER() OVER (PARTITION BY region_1 ORDER BY price ASC) as cheapest,
ROW_NUMBER() OVER (PARTITION BY region_1 ORDER BY price DESC) as expensive
FROM winemag_p1
) B
WHERE cheapest = 1 OR expensive = 1
GROUP BY region_1
ORDER BY region_1;
``
You can use window functions or subqueries to get the highest and lowest prices per region. Then get all rows with these prices and aggregate per region.
For instance:
select
region_1,
min(price) as low_price,
string_agg(variety, ', ') filter (where price = min_price) as low_price_varieties,
max(price) as high_price,
string_agg(variety, ', ') filter (where price = max_price) as high_price_varieties
from
(
select
region_1, variety, price,
min(price) over (partition by region_1) as min_price,
max(price) over (partition by region_1) as max_price
from winemag_p1
) with_min_and_max
where price in (min_price, max_price)
group by region_1
order by region_1;
As to your own query: This is an okay query. Here are my remarks:
ORDER BY in a subquery only makes sense, when limiting the rows (with FETCH FIRST ROWS), because a query result is an unordered data set by definition.
Why DISTINCT? There are no duplicates to remove.
You don't handle ties. If there are two top wines with the same price in a region for instance, you pick one arbirarily.
select * from
(select Id, Prodcut, Billing_date
, row_number() over (partition by Id, product order by Billing_date desc) as RowNumber
,sum(Revenue)
from Table1
group by 1,2,3,4,1) a
where a.rowNumber = 1
There are rows where Id+product combination repeats for latest billing date and which causing some data to be missed out. I am trying to add sum with row_number to sum all the ID&product combinations for the latest date but not able to make it work.
Can anyone please help me out here!
Data Sample Image
Database: Athena, Dbeaver
I would expect this to do what you want:
select *
from (select Id, Product, Billing_date,
row_number() over (partition by Id, product order by Billing_date desc) as seqnum,
sum(Revenue)
from Table1
group by Id, Product, Billing_date
) t1
where seqnum = 1;
Your group by columns do not seem correct. I'm surprised your query runs in any datbase.
Customer have ordered from different cities. Thus we have multiple cities against same customer_id. I want to display that city against customer id which has occurred maximum number of times , in case where customer has ordered same number of orders from multiple cities that city should be selected from where he has placed last order. I have tried something like
SELECT customer_id,delivery_city,COUNT(DISTINCT delivery_city)
FROM analytics.f_order
GROUP BY customer_id,delivery_city
HAVING COUNT(DISTINCT delivery_city) > 1
WITH cte as (
SELECT customer_id,
delivery_city,
COUNT(delivery_city) as city_count,
MAX(order_date) as last_order
FROM analytics.f_order
GROUP BY customer_id, delivery_city
), ranking as (
SELECT *, row_number() over (partition by customer_id
order by city_count DESC, last_order DESC) as rn
FROM cte
)
SELECT *
FROM ranking
WHERE rn = 1
select customer_id,
delivery_city,
amount
from
(
select t.*,
rank() over (partition by customer_id order by amount asc) as rank
from(
SELECT customer_id,
delivery_city,
COUNT(DISTINCT delivery_city) as amount
FROM analytics.f_order
GROUP BY customer_id,delivery_city
) t
)
where rank = 1
I have a table named Stud in which I have a column to store the total. Now I need to find the 5th largest total in total column. How to perform this operation?
Try this:
SELECT total FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY total DESC) as RN, total FROM Stud
) T
WHERE RN=5
Select total
From
(SELECT total,
row_number() over(order by total desc) as rn
From totalTable
)Z
Where rn=5
Also can be done using ROWNUM pseudocolumn
Select total
From
(SELECT total
FROM totalTable
ORDER BY total desc
)Z
Where ROWNUM=5
I need to return the following statement but I only want to return the TOP 5 of each Sale value only.....not all the records.
Select ID, Code, sum(Sale) as Sale from TableName
Where Code = 11
Group By ID, code
I do not want this!
Select TOP 5 ID, Code, sum(Sale) as Sale from TableName
Where Code = 11
Group By ID, code
With Cte as
( Select ID, Code, sale as Sales ,
row_number() over (partition by ID,code order by sale desc) as row_num
from TableName where code=11
)
Select Id,code,sum(sales) from cte
GROUP BY ID, code
WHERE row_num < 6
WITH TopSales AS (
SELECT *, RANK() OVER (PARTITION BY ID, Code ORDER BY Sale DESC) saleRank
FROM TableName
)
SELECT ID, Code, SUM(Sale) AS Sale
FROM TopSales
WHERE (Code = 11) AND (saleRank <= 5)
GROUP BY ID, code
select id, code, SUM (sale)
from
(
select id, code, sale,
ROW_NUMBER() over(partition by id, code order by sale desc) rn
from tablename
) v
where rn<=5
group by id, code
Probably you need something like:
;WITH sales (
SELECT
id,
code,
sale,
ROW_NUMBER() OVER (PARTITION BY id, code ORDER BY sales DESC) n
FROM
TableName
WHERE
Code = 11
)
SELECT
id, code, sum(sale) sale
FROM
sales
WHERE
n <= 5
GROUP BY
id,
code
ROW_NUMBER() and PARTITION BY help to find last 5 sales. Then you SUM only top (highest) 5.
This query returns sum of top 5 sales for each (id, code) group.
If you want to return just the top 5 results for each group you could do this:
with cte as
(ID, Code, Sale,ROW_NUMBER() over(partition by ID,
Code order by (select 0)) rownum
from TableName)
Select ID, Code, sum(Sale) as Sale from cte
Where Code = 11
and rownum<=5
Group By ID, code
If you want to return top 5 results with highest salary for each group you could do this:
with cte as
(ID, Code, Sale,ROW_NUMBER() over(partition by ID,
Code order by Sale desc) rownum
from TableName)
Select ID, Code, sum(Sale) as Sale from cte
Where Code = 11
and rownum<=5
Group By ID, code
select id, code, sum(sale) as sale from tablename
where code = 11
group by id, code
order by sum(sale) desc
limit 5