SQL return row when sum value is null - sql

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

Related

Finding Max Price and displaying multiple columns 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
);

Keep first record in group and populate rest with Null/0 in SQL?

I have the following table in my database:
date sales
1 2010-12-13 10
2 2010-12-13 10
3 2010-12-13 10
4 2010-12-13 10
5 2010-12-13 10
6 2010-12-14 20
7 2010-12-14 20
8 2010-12-14 20
9 2010-12-14 20
10 2010-12-14 20
Is there a way to attain the first record only and populate the rest with NULL or 0 for the remainder of the group? AS the grouping will be done by date and sales:
For example the intended output is:
date sales
1 2010-12-13 10
2 2010-12-13 0
3 2010-12-13 0
4 2010-12-13 0
5 2010-12-13 0
6 2010-12-14 20
7 2010-12-14 0
8 2010-12-14 0
9 2010-12-14 0
10 2010-12-14 0
So essentially to keep the first record but make the rest of the records in the group be 0 (maybe Null if that is quicker/easier)
The closest i have got to solving this is attaining just the first record through an inner join - but I think a partition over may solve it - just stuck at the moment!
Any help appreciated!
Using SQLite - but also GCP (SQL) is accesible to me
This might work in SQLite:
CASE WHEN id = MIN(id) OVER(PARTITION BY date) THEN sales ELSE 0 END as sales
If it doesn't you can prepare a subquery that has only the min ID per date and join it in:
SELECT
CASE WHEN y.id IS NULL THEN 0 ELSE sales END as sales
FROM
x
LEFT JOIN (SELECT MIN(id) as id FROM x GROUP BY date) y ON x.id= y.id

SQL Temp table Array to perfrom rolling caluclations

I wish to use some sort of SQL array to subtract values from a certain row (QTYOnHand) that decreases that row value every time and throws it into a rolling calculation for the other rows. I've been thinking of some sort of Self Join/Temp Table solution, but not sure how to formulate. Also, All the results will be partitioned by the ItemID below. Help would be appreciated.
Here's some data, If I do a simple row by row subtraction I will get this: 17-3 = 14, 17-5 = 12 and so on.
(Item_ID) (ItemQty) (QTYOnHand) (QtyOnHand - ItemQty)
123 3 17 14
123 5 17 12
123 4 17 13
456 7 12 5
456 8 12 4
456 2 12 10
456 3 12 9
789 2 6 4
789 2 6 4
789 2 6 4
These are the results that I want, where I subtract every next value from the new QTYOnHand-ItemQty column value. Looks like 17-3 then 14 -5 then 9 -4 for Item_ID (123):
(Item_ID) (ItemQty) (QTYOnHand) (QtyOnHand - ItemQty)
123 3 17 14
123 5 17 9
123 4 17 5
456 7 12 5
456 8 12 -3
456 2 12 -5
456 3 12 -8
789 2 6 4
789 2 6 2
789 2 6 0
try the following:
;with cte as
(
select *, ROW_NUMBER() over (partition by Item_ID order by Item_ID) rn
from YourTable
)
, cte2 as
(
select Item_ID, ItemQty, QTYOnHand, Case when rn = 1 then QTYOnHand else 0 end - ItemQty as calc, rn
from cte
)
select Item_ID, ItemQty, QTYOnHand, sum(calc) over (partition by Item_ID order by rn) as [QtyOnHand - ItemQty]
from cte2 t1
Please find the db<>fiddle here.

update table query from other table

I have the following problem:
In my database I have 1st table : item_price
Id_item Dept Price
1 7 1500
2 7 100
3 7 200
4 7 300
5 7 400
6 7 0
7 7 0
8 7 0
9 7 0
10 7 0
And I have 2nd table : Order_history
Order_no Id_item Dept Price Date_order
A1 1 2 700 01/05/2014
A2 2 3 800 02/21/2014
A3 3 7 200 03/25/2013
A4 3 7 300 04/15/2014
A5 4 7 300 05/05/2014
A6 5 7 400 06/15/2014
A7 6 7 120 07/16/2014
A8 7 7 1400 08/19/2014
A9 8 7 150 09/25/2014
A10 9 7 4500 10/31/2014
A11 10 7 8000 11/15/2014
All I want to do now is:
I want to update field price in item_price WHERE Id_item in item_price = Id_item in Order History
dept in item_price = dept in order_history AND
Date_Order = 01/05/2014 - 11/07/2014
something like ===
update item_price
set price = (select item_number from item_history )
where date_order = '01/01/2014' - '11/07/2014' and dept = '7';
Can you guys help me?
Oracle does provide support for updates with joins. What you can do is something like this (note I have not tested this):
MERGE
INTO item_price
USING (
SELECT ip.Id_item AS rid, oh.price as hist_price
FROM item_price ip
JOIN Order_history oh
ON oh.id_item = ip.id_item
WHERE
oh.date_order between TO_DATE('01/01/2014') and TO_DATE('11/07/2014')
)
ON (Id_item = rid)
WHEN MATCHED THEN
UPDATE
SET price = hist_price;
MySQL syntax would be something like this:
UPDATE item_price ip
JOIN Order_history oh ON oh.id_item = ip.id_item
WHERE
oh.date_order between
STR_TO_DATE('01/01/2014', '%m/%d/%Y') and
STR_TO_DATE('11/07/2014', '%m/%d/%Y')
SET ip.price = oh.price;
SQL
Test on Dev First and verify results! Please
UPDATE item
SET item.Price = history.price
FROM dbo.item_price item
JOIN dbo.Order_History history ON item.Id_Item= history.Id_Item AND item.Dept = History.Dept
WHERE history.Date_Order Between '01/05/2014' AND '11/07/2014'

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