using sql join on three tables - sql

I have 3 tables which maintains stock entries for each products/items. These three tables like below :
Table : ItemStock (to maintain remaining stock of each item)
Id ItemId OpgQty BranchID CurrentStock
1 7 0 1 8
2 7 0 2 3
3 6 0 1 2
4 6 0 2 0
Table : ItemPurchase (StockIn)
Id ItemId Qty BranchID
1 7 5 1
2 7 4 2
3 7 6 1
4 7 2 2
5 6 4 1
6 6 2 2
7 6 2 1
Table : ItemSale (StockOut)
Id ItemId Qty BranchID
1 7 2 1
2 7 3 2
3 7 1 1
4 6 4 1
5 6 2 2
Desired Output (based on sql queries)
I want to have result like below : (part of report)
Id ItemId OpgQty BranchId StockIn StockOut CurrentStock
1 7 0 1 11 3 8
2 7 0 2 6 3 3
3 6 0 1 6 4 2
4 6 0 2 2 2 0
I was trying to get the desired result but was not able to do so. Please help!!!

try this;
select
m.Id,
m.ItemId,
m.OpgQty,
m.BranchID,
si.StockIn,
m.CurrentStock-si.StockIn StockOut,
m.CurrentStock
from
ItemStock m
inner join
(
select
ItemId,BranchId,sum(Qty) as StockIn
from
ItemPurchase
group by ItemId,BranchId
) si on si.ItemId=m.ItemId and si.BranchId=m.BranchId

A very simple query that gives the desired result is :
select *,
(select sum(Qty)
from ItemPurchase
where ItemPurchase.ItemId = ItemStock.ItemId and
ItemPurchase.BranchId = ItemStock.BranchId) as StockIn,
(select sum(Qty)
from ItemSale
where ItemSale.ItemId = ItemStock.ItemId and
ItemSale.BranchId = ItemStock.BranchId) as StockOut
from ItemStock

Two subqueries with group by and aggregation will get what you want.
select
s.*,
coalesce([ip].StockIn, 0) as StockIn, -- In case of no records in ItemPurchase or ItemSale, coalesce is neccessary.
coalesce([is].StockOut, 0) as StockOut
from ItemStock s
left join (
select sum(Qty) as StockIn, ItemId, BranchId
from ItemPurchase
group by ItemId, BranchId
) [ip] on s.ItemId = [ip].ItemId and s.BranchId = [ip].BranchId
left join (
select sum(Qty) as StockOut, ItemId, BranchId
from ItemSale
group by ItemId, BranchId
) [is] on s.ItemId = [is].ItemId and s.BranchId = [is].BranchId
See demo in sqlfiddle.

Please
Try This ... I hope you consider this too.

Related

Get max record for each group of records, link multiple tables

I seek to find the maximum timestamp (ob.create_ts) for each group of marketid's (ob.marketid), joining tables obe (ob.orderbookid = obe.orderbookid) and market (ob.marketid = m.marketid). Although there are a number of solutions posted like this for a single table, when I join multiple tables, I get redundant results. Sample table and desired results below:
table: ob
orderbookid
marketid
create_ts
1
1
1664635255298
2
1
1664635255299
3
1
1664635255300
4
2
1664635255301
5
2
1664635255302
6
2
1664635255303
table: obe
orderbookentryid
orderbookid
entryname
1
1
'entry-1'
2
1
'entry-2'
3
1
'entry-3'
4
2
'entry-4'
5
2
'entry-5'
6
3
'entry-6'
7
3
'entry-7'
8
4
'entry-8'
9
5
'entry-9'
10
6
'entry-10'
table: m
marketid
marketname
1
'market-1'
2
'market-2'
desired results
ob.orderbookid
ob.marketid
obe.orderbookentryid
obe.entryname
m.marketname
3
1
6
'entry-6'
'market-1'
3
1
7
'entry-7'
'market-1'
6
2
10
'entry-10'
'market-2'
Use ROW_NUMBER() to get a properly filtered ob table. Then JOIN the other tables onto that!
WITH
ob_filtered AS (
SELECT
orderbookid,
marketid
FROM
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY
marketid
ORDER BY
create_ts DESC
) AS create_ts_rownumber
FROM
ob
) ob_with_rownumber
WHERE
create_ts_rownumber = 1
)
SELECT
ob_filtered.orderbookid,
ob_filtered.marketid,
obe.orderbookentryid,
obe.entryname,
m.marketname
FROM
ob_filtered
JOIN m
ON m.marketid = ob_filtered.marketid
JOIN obe
ON ob_filtered.orderbookid = obe.orderbookid
;

SQL Query to get multiple resultant on single column

I have a table that looks something like this:
id name status
2 a 1
2 a 2
2 a 3
2 a 2
2 a 1
3 b 2
3 b 1
3 b 2
3 b 1
and the resultant i want is:
id name total count count(status3) count(status2) count(status1)
2 a 5 1 2 2
3 b 4 0 2 2
please help me get this result somehow, i can just get id, name or one of them at a time, don't know how to put a clause to get this table at once.
Here's a simple solution using group by and case when.
select id
,count(*) as 'total count'
,count(case status when 3 then 1 end) as 'count(status1)'
,count(case status when 2 then 1 end) as 'count(status3)'
,count(case status when 1 then 1 end) as 'count(status2)'
from t
group by id
id
total count
count(status3)
count(status2)
count(status1)
2
5
1
2
2
3
4
0
2
2
Fiddle
Here's a way to solve it using pivot.
select *
from (select status,id, count(*) over (partition by id) as "total count" from t) tmp
pivot (count(status) for status in ([1],[2],[3])) pvt
d
total count
1
2
3
3
4
2
2
0
2
5
2
2
1
Fiddle

SQL - Recursively finding count in another table

I have a table which has both category and subcategory such as this :
CategoryID CategoryName ParentCategoryID
1 CatA NULL
2 CatA1 1
3 CatA2 1
4 CatA3 1
5 CatB NULL
6 CatB1 5
7 CatC NULL
8 CatC1 7
I have another table where I have mappings
MappingID CategoryID ItemID
1 2 1
2 3 1
3 6 2
4 8 3
5 2 3
6 3 4
7 4 4
8 2 3
9 3 4
10 2 2
11 2 2
12 2 2
13 2 3
14 2 1
I need a result set where count of all items per category is displayed such as :
Category No. of Items
1 12
5 1
7 1
Could you someone guide me with this?
I have tried using a CTE :
WITH CTE (CategoryID, CategoryName, ParentID, CategoryParentName)
AS
(
SELECT CategoryID,
CategoryName,
ParentCategoryID,
CategoryName AS CategoryParentName
FROM [dbo].[Category]
WHERE ParentCategoryID IS NULL
AND IsDeleted = 0
UNION ALL
SELECT garages.CategoryID,
garages.CategoryName,
garages.ParentCategoryID,
traces.CategoryName AS CategoryParentName
FROM [dbo].[Category] AS garages
INNER JOIN CTE AS traces ON traces.CategoryID= garages.ParentCategoryID
)
SELECT gr.CategoryID, COUNT(map.CategoryID) AS Total
FROM CTE gr
INNER JOIN [dbo].[CategoryMapping] map ON gr.CategoryID = map.CategoryID
GROUP BY gr.CategoryID
If there are just two levels of categories than there is no need for recursive query
select coalesce(c.ParentCategoryID, c.CategoryID), count(*)
from Category c
join CategoryMapping m on c.CategoryID = m.CategoryID
group by coalesce(c.ParentCategoryID, c.CategoryID)
Obviously, categories without mapping won't be there.

MS-Access SQL loops

I would like to apply a for loop in this sql statement in ms-access something like:
for(i=0;i<8;i++)
{
UPDATE current_stock SET current_stock.quantity = DLookup("quantity","current_stock","stock_id=i")-DLookup("req_quantity","Bom_dell","lap_id=(SELECT lap_id FROM laptop_info WHERE model_name='Dell Inspiron')" And "stock_id=i")
WHERE stock_id=1;
}
Please advise if there is any method in MS-access to be able to do something similar to a for loop using sql queries.
Bom_dell
bom_id lap_id stock_id req_quantity
1 1 1 1
2 1 2 3
3 1 3 6
4 1 4 1
5 1 5 1
6 1 6 2
7 2 7 7
8 2 8 8
9 2 9 1
10 2 10 1
11 2 11 1
12 2 12 3
current_stock
ID lap_id stock_id quantity
1 1 1 11
2 1 2 11
3 1 3 11
lap_info
lap_id model_name model_num price
1 Dell Inspiron INS81 35000
2 Dell XLS XL91 24000
Sample query
UPDATE (SELECT laptop_info.model_name, current_stock.stock_id, Bom_dell.req_quantity, current_stock.quantity
FROM (current_stock INNER JOIN laptop_info ON current_stock.lap_id = laptop_info.lap_id) INNER JOIN Bom_dell ON current_stock.stock_id = Bom_dell.stock_id)
SET quantity=quantity-req_quantity
WHERE stock_id BETWEEN 1 AND 3
AND model_name='Dell Inspiron'
UPDATE (SELECT laptop_info.model_name, current_stock.stock_id, Bom_dell.req_quantity, current_stock.quantity
FROM (current_stock INNER JOIN laptop_info ON current_stock.lap_id = laptop_info.lap_id) INNER JOIN Bom_dell ON current_stock.stock_id = Bom_dell.stock_id) SET quantity = quantity-req_quantity
WHERE stock_id BETWEEN 1 AND 3
AND model_name IN ([Forms]![Invoice1]![laptop_id])
You seem to be looking for something on the lines of:
UPDATE (current_stock
INNER JOIN laptop_info ON laptop_info.stock_id=current_stock.stock_id)
INNER JOIN Bom_dell ON Bom_dell.lap_id = laptop_info.lap_id
SET current_stock.quantity = current_stock.quantity - Bom_dell.req_quantity
WHERE stock_id Between 1 And 8
AND model_name='Dell Inspiron'
Try this. I have used aliases - a is for the current_stock table and b is for the sub query. This assumes that you have one line per stock id in bom_dell.
UPDATE current_stock AS a
INNER JOIN (
SELECT bom_dell.stock_id, lap_info.model_name, bom_dell.req_quantity
FROM bom_dell
INNER JOIN lap_info ON bom_dell.lap_id = lap_info.lap_id
WHERE (((bom_dell.stock_id) Between 1 And 3)
AND ((lap_info.model_name)="Dell Inspiron"))) AS b
ON a.Stock_id = b.Stock_id SET a.quantity = [a].[quantity]+[b].[req_quantity];

SQL query to show most ordered product

I have this table structure
Product
product_id (PK)
name
Order_Detail
order_detail_id
product_id
quantity
Example data
Product :
1 product1
2 product2
3 product3
4 product4
5 product5
Order_Detail :
1 3 2
2 3 1
3 3 1
4 2 1
5 2 1
6 1 1
7 4 1
8 5 1
9 1 1
10 2 1
11 3 1
Please help me to get top 3 ordered product based on how many times the product ordered ?
I think this migth work:
SELECT p.`product_id`, p.`name`, SUM(o.`quantity`) AS quantity
FROM `Order_Detail` AS o
INNER JOIN `Product` AS p
ON o.`product_id` = p.`product_id`
GROUP BY o.`product_id`
ORDER BY SUM(o.`quantity`) DESC, p.`name` ASC
LIMIT 3