Finding Max Price and displaying multiple columns SQL - sql

I have a table that looks like this:
customer_id item price cost
1 Shoe 120 36
1 Bag 180 50
1 Shirt 30 9
2 Shoe 150 40
3 Shirt 30 9
4 Shoe 120 36
5 Shorts 65 14
I am trying to find the most expensive item each customer bought along with the cost of item and the item name.
I'm able to do the first part:
SELECT customer_id, max(price)
FROM sales
GROUP BY customer_id;
Which gives me:
customer_id price
1 180
2 150
3 30
4 120
5 65
How do I get this output to also show me the item and it's cost in the output? So output should look like this...
customer_id price item cost
1 180 Bag 50
2 150 Shoe 40
3 30 Shirt 9
4 120 Shoe 36
5 65 Shorts 14
I'm assuming its a Select statement within a Select? I would appreciate the help as I'm fairly new to SQL.

One method that usually has good performance is a correlated subquery:
select s.*
from sales s
where s.price = (select max(s2.price)
from sales s2
where s2.customer_id = s.customer_id
);

Related

SQL Server : how to count a column that if exist duplicate data, it reuse duplicate data first exist count number

Table A
shop
amount
count
sameShopCount
shop5
100
1
1
shop2
99
2
1
shop3
98
3
1
shop4
97
4
1
shop1
96
5
1
shop2
95
6
2
shop4
94
7
2
shop5
93
8
2
shop5
92
9
3
shop1
91
10
2
shop5
90
11
4
shop3
89
12
2
Expected Result (order by amount desc):
shop
amount
expected result
shop5
100
1
shop2
99
2
shop3
98
3
shop4
97
4
shop1
96
5
shop2
95
2
shop4
94
4
shop5
93
1
shop5
92
1
shop1
91
5
shop5
90
1
shop3
89
3
I want to count shop column similar to count column in Table A. But also if shop exist more than 1 time it will reuse the first exist count number.
How can I achieved this with/without a temp table in SQL Server respectively? (SQL Server 2014 - build v12.0.6108.1)
I had tried something like:
ROW_NUMBER() OVER (ORDER BY amount DESC)
DENSE_RANK() OVER (PARTITION BY shop ORDER BY amount DESC)
Try using max and dense_rank window functions as the following:
with max_shop_amount as
(
select *,
max(amount) over (partition by shop) as mx
from table_name
)
select shop, amount,
dense_rank() over (order by mx desc) expected
from max_shop_amount
order by amount desc
See demo

Update and delete at the same time Postgres

I have a table of this kind
Table of items with price under 100
Prod_ID
PRICE
1
45
2
67
3
89
4
91
5
23
6
98
Now I Want to write PostgresSQL command to update the price of each item increasing it by $10 and want to delete all the items with price more than $100
After the query, the table should be:
Prod_ID
PRICE
1
55
2
77
3
99
5
33
How can I do this?
You can use update first and then delete.
UPDATE your_table_name set PRICE=PRICE + 10;
DELETE FROM your_table_name WHERE PRICE > 100;

SQL return row when sum value is null

I got two tables. One with a bill of material and one with purchasing orders. Now I want to display the full bill of material of a product with the total on order amounts from the table purchasing.
**Billofmaterials**
BOM_ID BOM_Prod_id BOM_item_id
1 5 11
2 5 13
3 6 11
4 6 15
5 6 20
Example prod_id (product id) 6 has 3 items (id 11, 15 and 20).
**Purchasing**
PU_ID PU_item_id PU_amount PU_status
1 11 100 On order
2 11 650 On order
3 11 40 Received
4 20 600 On order
5 8 10 On order
6 15 150 Received
Now i got the following SQL
SELECT
BOM_item_id,
SUM(DISTINCT purchasing.PU_amount) as total_on_order
FROM Billofmaterials
LEFT JOIN purchasing
ON Billofmaterials.BOM_item_id= purchasing.PU_item_id
AND purchasing.PU_status != 'Received'
AND BOM_prod_id = 6
GROUP BY BOM_item_id
This query returns the following:
**Query result**
BOM_item_id total_on_order
11 750
20 600
Because there is only one received purchase order for BOM_item_id 15 it doesn't return a value. Now i want to retun BOM_item_id 15 also but with a total_on_order as 0 like:
**Expected result**
BOM_item_id total_on_order
11 750
15 0
20 600
What SQL feature/function do I need to use to get the expected result?
You can try the below -
SELECT BOM_item_id,coalesce(total_on_order,0) as total_on_order
FROM Billofmaterials left join
(
select PU_item_id,SUM(purchasing.PU_amount) as total_on_order
from purchasing
where purchasing.PU_status != 'Received'
group by PU_item_id
) purchasing
ON Billofmaterials.BOM_item_id= purchasing.PU_item_id
where BOM_prod_id = 6

Calculate fixed Cost/day for multiple services on same date

Desired Output table T with Calculated Cost column:
SvcID Code ID Date Mins Units Cost
1 3000 15 4/4/2016 60 10 70
2 3000 17 4/4/2016 45 10 0
3 3000 15 5/2/2016 30 10 70
4 3000 18 5/2/2016 60 10 0
5 3000 10 5/2/2016 30 10 0
6 4200 16 2/1/2016 60 4 60
7 4200 9 2/1/2016 30 2 30
Query for calculating and displaying:
SELECT
...
,CASE
WHEN Code=4200 THEN Units*15
WHEN Code=3000 THEN ?
END AS Cost
FROM ...
WHERE Code IN ('3000','4200')
GROUP BY ....;
Cost should be a total of 70 for all services offered on same date for Code 3000, irrespective of number of services offered. No relation between Minutes and Units for this Code for calculating Cost.
One way could be to calculate cost as 70 for any one service and make the remaining services cost 0 for same date. Can this be done in the CASE statement?
Any better way to achieve this?
You need to Investigate Window functions MSDN.
Your case would become something like this:
-- New select statament
SELECT
...
,CASE
WHEN Code=4200 THEN Units*15
WHEN Code=3000 THEN ( CASE WHEN DuplicateNum = 1 THEN 70 ELSE 0 END )?
END AS Cost
FROM(
-- Your current query (with case statement removed) and ROW_NUMBER() function added
SELECT
..., ROW_NUMBER() OVER( PARTITION BY Code, Date ORDER BY ID ) AS DuplicateNum
FROM ...
WHERE Code IN ('3000','4200')
GROUP BY ....
) AS YourCurrentQuery;

Finding double mrp's in SQL

I have table with productcode and mrp like
Pcode MRP
1 30
2 30
2 35
3 100
4 150
4 150
5 45
6 120
6 122
6 125
I want to find which productcodes have more than two mrp.
Thanks in advance.
If you get the count and use the having clause, you should get what you are looking for.
select pcode, count(pcode)
From tab
group by pcode
having count(pcode) > 1