Using two aggregate function - min and max on same query - sql

Here is my product table's data -
product_id category discount
454 C-10 10
357 C-10 9
64 C-10 10
294 C-11 17
449 C-11 17
471 C-11 17
89 C-11 12
56 C-11 10
I want to get the max discount for every product category and if any category has multiple products having same discount, the product having the minimum
product_id should be selected.
Desired output -
product_id category discount
64 C-10 10
294 C-11 17
I tried below two query but not working -
select category,min(product_id),max(discount)
from Product
group by category
Your help is very much appreciated. Thanks!

Using ROW_NUMBER is helpful here:
WITH cte AS (
SELECT product_id, category, discount,
ROW_NUMBER() OVER (PARTITION BY category
ORDER BY discount DESC, product_id) rn
FROM Product
)
SELECT product_id, category, discount
FROM cte
WHERE rn = 1;
Or, we could even do this without using a subquery/CTE:
SELECT TOP 1 WITH TIES product_id, category, discount
FROM Product
ORDER BY
ROW_NUMBER() OVER (PARTITION BY category
ORDER BY discount DESC, product_id);

use row_number()
select * from
(
select *,row_number() over(partition by category order by discount desc, poroduct_id asc) rn
from tablename
)A where rn=1
OR
use correlated subquery
select * from tablename a where discount in
(select max(discount) from tablename b where a.category=b.category
having min(b.product_id)=a.product_id)

use outer apply
with cte as
(
select 454 as product_id, 'C-10' as category, 10 as discount union all
select 357,'C-10',9 union all
select 64,'C-10',10 union all
select 294,'C-11',17 union all
select 449,'C-11',17 union all
select 471,'C-11',17 union all
select 89,'C-11', 12 union all
select 56,'C-11', 10
) select distinct p1.category,a.product_id,a.discount
from cte p1
outer apply ( select top 1 p2.*
from cte p2 where p1.category=p2.category
order by discount desc, product_id asc
) a
output
category product_id discount
C-10 64 10
C-11 294 17
demo link

Related

List the most up-to-date product of each category,postqresql queries

user_id product_id category_id date_added date_update
1 2 1 2.3.2021 null
1 3 1 2.3.2020 2.4.2023
1 4 2 2.3.2020 null
1 5 2 2.3.2020 2.4.2023
2 5 2 2.3.2020 2.4.2023
2 4 1 2.3.2020 null
List the most up-to-date product of each category
You can use row_number()
select * from
(
select *,row_number() over(parition by userid,category_id order by date_update) as rn
from tablename
)A where rn=1
OR you can also use distinct on
select distinct on (user_id,category_id) *
FROM tablename
ORDER BY user_id,category_id, date_update
List the most up-to-date product of each category
You can use distinct on. Let me assume that if the update date is null, then you want the creation date:
select distinct on (category_id) t.*
from t
order by category_id, coalesce(date_update, date_added) desc;
If you wanted this per user/category combination, the logic would be:
select distinct on (user_id, category_id) t.*
from t
order by user_id, category_id, coalesce(date_update, date_added) desc;
Using Window function
select u_id,c_id, p_id, coalesce (date_update, date_added) as date ,
rank () over (partition by u_id, c_id order by coalesce (date_update, date_added) desc) as r
from inventory
) t where r = 1

Limit top pair of columns

The data I am working with looks like below-
category_id subcategory_id date quantities
123 45 2020-02-01 500
123 45 2020-02-13 400
456 35 2020-05-09 350
456 35 2020-05-15 250
456 35 2020-06-18 200
.
.
.
n such columns
Quantities are sorted in descending order
I want to get the data (as seen above) for the first (top) 10 unique pairs of (category_id, subcategory_id). Just like we use limit 10 to get the first 10 records, I want to limit by the top 10 unique pairs of (category_id, subcategory_id) and get the all the data as seen above.
Below is for BigQuery Standard SQL
#standardSQL
SELECT * EXCEPT(rn) FROM (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY category_id, subcategory_id ORDER BY quantities DESC) rn
FROM `project.dataset.table`
)
WHERE rn <= 10
Another - more BigQuery'ish alternative is below
#standardSQL
SELECT TopN.* FROM (
SELECT ARRAY_AGG(t ORDER BY quantities DESC LIMIT 10) topN
FROM `project.dataset.table` t
GROUP BY category_id, subcategory_id
) t, t.topN
If you want 10 rows, each with different category_id/subcategory_id pairs, then you can use:
select t.* except (seqnum)
from (select t.*,
row_number() over (partition by category_id, subcategory_id order by quantities desc) as seqnum
from t
) t
where seqnum = 1
order by quantities desc
limit 10;
This gets the first row (by quantities) for each id pair and then limits to the 10 largest values.

SQL sum grouped by field with all rows

I have this table:
id sale_id price
-------------------
1 1 100
2 1 200
3 2 50
4 3 50
I want this result:
id sale_id price sum(price by sale_id)
------------------------------------------
1 1 100 300
2 1 200 300
3 2 50 50
4 3 50 50
I tried this:
SELECT id, sale_id, price,
(SELECT sum(price) FROM sale_lines GROUP BY sale_id)
FROM sale_lines
But get the error that subquery returns different number of rows.
How can I do it?
I want all the rows of sale_lines table selecting all fields and adding the sum(price) grouped by sale_id.
You can use window function :
sum(price) over (partition by sale_id) as sum
If you want sub-query then you need to correlate them :
SELECT sl.id, sl.sale_id, sl.price,
(SELECT sum(sll.price)
FROM sale_lines sll
WHERE sl.sale_id = sll.sale_id
)
FROM sale_lines sl;
Don't use GROUP BY in the sub-query, make it a co-related sub-query:
SELECT sl1.id, sl1.sale_id, sl1.price,
(SELECT sum(sl2.price) FROM sale_lines sl2 where sl2.sale_id = sl.sale_id) as total
FROM sale_lines sl1
In addition to other approaches, You can use CROSS APPLY and get the sum.
SELECT id, sale_id,price, Price_Sum
FROM YourTable AS ot
CROSS APPLY
(SELECT SUM(price) AS Price_Sum
FROM YourTable
WHERE sale_id = ot.sale_id);
SELECT t1.*,
total_price
FROM `sale_lines` AS t1
JOIN(SELECT Sum(price) AS total_price,
sale_id
FROM sale_lines
GROUP BY sale_id) AS t2
ON t1.sale_id = t2.sale_id

How to build SQL to capture most unique value?

I am trying to build a query results with SQL. Here is my table:
CUST_ID ORDER_ID STORE_FREQUENCY
---------- ----------- ---------------
100 20122 500
100 20100 500
100 20100 737
200 20119 287
300 20130 434
300 20150 434
300 20130 434
300 20120 120
The expected output is:
CUST_ID UNIQUE_ORDERS TOP_STORE
--------- ----------------- ---------
100 2 737
200 1 287
300 3 434
The requirement for the output is:
TOP_STORE = Per CUST_ID, sort the STORE_FREQUENCY column by DESC and get the greatest store frequency
UNIQUE_ORDERS = Per CUST_ID, the number of unique ORDER_IDs in the column
I have started this SELECT statement, but having difficulties completing it to include the 2 columns correctly:
Select cust_id, Count(order_id) as unique_orders
From ORDERS_TABLE
Group By Order_ID
Can you help me complete the 2 columns?
Use aggregate functions such as COUNT(DISTINCT ...) and MAX()
SELECT CUST_ID, COUNT(DISTINCT ORDER_ID), MAX(STORE_FREQUENCY )
FROM TableName
GROUP BY CUST_ID
Here's a DEMO.
It seems to be that the top store should be the store with the greatest number of orders. If so, then CUST_ID 100 should have store 500 as the top store, not 737. In other words, I would expect the following output:
This requirement changes the query strategy, because we no longer can just do a single simple aggregation over the entire table. One approach is to do a separate calculation to find the top store for each customer, then join that result to a query similar to the other answers.
WITH cte AS (
SELECT CUST_ID, STORE_FREQUENCY, cnt,
ROW_NUMBER() OVER (PARTITION BY CUST_ID ORDER BY cnt DESC) rn
FROM
(
SELECT CUST_ID, STORE_FREQUENCY,
COUNT(*) OVER (PARTITION BY CUST_ID, STORE_FREQUENCY) cnt
FROM yourTable
) t
)
SELECT
t1.CUST_ID,
t1.UNIQUE_ORDERS,
t2.TOP_STORE
FROM
(
SELECT CUST_ID, COUNT(DISTINCT ORDER_ID) AS UNIQUE_ORDERS
FROM yourTable
GROUP BY CUST_ID
) t1
INNER JOIN
(
SELECT CUST_ID, STORE_FREQUENCY AS TOP_STORE
FROM cte
WHERE rn = 1
) t2
ON t1.CUST_ID = t2.CUST_ID;
Demo

SQL for highest sold Products

Order Sample data:
ORDER_DAY ORDER_ID PRODUCT_ID QUANTITY PRICE
---------- --------- ----------- ---------- ---------
01-JUL-11 O1 P1 5 5
01-JUL-11 O2 P2 2 10
01-JUL-11 O3 P3 10 25
01-JUL-11 O4 P1 20 5
02-JUL-11 O5 P3 5 25
02-JUL-11 O6 P4 6 20
02-JUL-11 O7 P1 2 5
02-JUL-11 O8 P5 1 50
02-JUL-11 O9 P6 2 50
02-JUL-11 O10 P2 4 10
Q: Get me highest sold Products (Qty* Price) on both days
Desired output :
DATE PRODUCT_ID SOLD_AMOUNT
01-JUL-11 P3 250
02-JUL-11 P3 125
Try following query:
select order_day, product_id, totalsale
from (select order_day,
product_id,
nvl(QUANTITY, 0) * PRICE as totalsale,
dense_rank() over(partition by ORDER_DAY order by(nvl(QUANTITY, 0) * PRICE) desc) as maxsum
from orders )
where maxsum = 1;
You would start with getting the sold amount per day and product. With this data you first select the maximum profit per day and then select those entries that match this:
WITH PRODUCT_PER_DAY AS
(
SELECT ORDER_DAY, PRODUCT_ID, SUM(QUANTITY * PRICE) AS SOLD_AMOUNT
FROM MYTABLE
GROUP BY ORDER_DAY, PRODUCT_ID
)
SELECT ORDER_DAY, PRODUCT_ID, SOLD_AMOUNT
FROM PRODUCT_PER_DAY
WHERE (ORDER_DAY, SOLD_AMOUNT) IN
(
SELECT ORDER_DAY, MAX(SOLD_AMOUNT)
FROM PRODUCT_PER_DAY
GROUP BY ORDER_DAY
)
ORDER BY ORDER_DAY, PRODUCT_ID;
select b.product_id,a.order_day,a.total_price from(select order_day, max(quantity*price)as total_price from order group by order_day)a
join (select product_id , quantity * price as total_amount from order)b on
a.total_price= b.total_price
Try this out (modify the table and column names as per your needs):
Select a.order_day, b.product_id, a.sales
from
(select order_day, max(quantity*price) as sales
from ordr
group by order_day) a
inner join
(select order_day, product_id, quantity*price as sales
from ordr) b
on a.order_day = b.order_day and a.sales = b.sales;
with temp as
(select order_day,product_id,sum(quantity*price) qp
from orders_amazn
group by order_day,product_id
)
select * from (select order_day,product_id,qp,
dense_rank() over (partition by order_day order by qp desc) rnk
from temp)
where rnk=1;
select date,product_id,max(product_id*price) as sold_amount form order
group by order_day
order by order_day
select t.ORDER_DAY as date1 ,t.PRODUCT_ID,max(t.quantity * t.price)
as sold_amount from table t group by t.ORDER_DAY,t.PRODUCT_ID
Kindly use this query you will be the desired output.I have tried in MySQL.
SELECT
order_date,
Product_id,
sold_amount
FROM
(
SELECT
date_format(order_day,'%d-%b-%y') AS order_date,
Product_id,
SUM(price*quantity) AS sold_amount
FROM
ecommerce
GROUP BY
date_format(order_day,'%d-%b-%y'),
product_id) a
WHERE
(
order_date,sold_amount) IN
(
SELECT
DATE,
MAX(sold_amt) AS sold_amount
FROM
(
SELECT
date_format(order_day,'%d-%b-%y') AS DATE,
product_id,
SUM(price*quantity) AS sold_amt
FROM
ecommerce
GROUP BY
date_format(order_day,'%d-%b-%y'),
product_id)a
GROUP BY
DATE)
select order_day as orderdate,product_id,max(quantity * price) as sold_amount
from order
group by order_day
order by product_id