How to calculate Sum and Subtraction from two different table - sql

I have two table "tbl_In_Details" and "tbl_Out_Details" Sample data for tbl_In_Details
sample data for tbl_In_Details
ID Item_Name Rate Quantity Source_company
1 wire 10 4 2020-04-21 22:47:29.083
2 Tea 4 20 2020-04-21 22:47:52.823
Sample data for tbl_Out_Details
ID Item_Name Quantity Created_Date
1 wire 1 2020-04-21 22:48:48.233
2 wire 2 2020-04-21 22:50:16.367
3 Tea 2 2020-04-21 23:48:39.94
Now i want to calculate current stock i.e. (incoming - Outgoing) as Current_Stock
i tried in such a way but not getting proper record please guide me where i need to modify my query:
Select O.Item_Name,
sum(CAST(I.Quantity AS INT))as Incoming_Quantity ,
SUM(CAST(o.Quantity as int)) as Outgoing_Quantity ,
(sum(CAST(I.Quantity AS INT)) - SUM(CAST(o.Quantity AS INT))) As Current_Stock
from tbl_In_Details I inner join tbl_Out_Details O
ON I.Item_Name = o.Item_Name group by O.Item_Name
My output should be
Item_Name Incoming_Quantity Outgoing_quantity Current_Stock
Wire 4 3 1
Tea 20 2 18

Use union all and aggregation:
select item_name, sum(in_quantity) as in_quantity, sum(out_quantity) as out_quantity,
sum(in_quantity) - sum(out_quantity) as in_stock
from ((select item_name, quantity as in_quantity, 0 as out_quantity
from incoming
) union all
(select item_name, 0, quantity
from outgoing
)
) io
group by item_name;

Related

How to find out first product item client purchased whose bought specific products?

I want to write a query to locate a group of clients whose purchased specific 2 product categories, at the same time, getting the information of first transaction date and first item they purchased. Since I used group by function, I could only get customer id but not first item purchase due to the nature of group by. Any thoughts to solve this problem?
What I have are transaction tables(t), customer_id tables(c) and product tables(p). Mine is SQL server 2008.
Update
SELECT t.customer_id
,t.product_category
,MIN(t.transaction_date) AS FIRST_TRANSACTION_DATE
,SUM(t.quantity) AS TOTAL_QTY
,SUM(t.sales) AS TOTAL_SALES
FROM transaction t
WHERE t.product_category IN ('VEGETABLES', 'FRUITS')
AND t.transaction_date BETWEEN '2020/01/01' AND '2022/09/30'
GROUP BY t.customer_id
HAVING COUNT(DISTINCT t.product_category) = 2
**Customer_id** **transaction_date** **product_category** **quantity** **sales**
1 2022-05-30 VEGETABLES 1 100
1 2022-08-30 VEGETABLES 1 100
2 2022-07-30 VEGETABLES 1 100
2 2022-07-30 FRUITS 1 50
2 2022-07-30 VEGETABLES 2 200
3 2022-07-30 VEGETABLES 3 300
3 2022-08-01 FRUITS 1 50
3 2022-08-05 FRUITS 1 50
4 2022-08-07 FRUITS 1 50
4 2022-09-05 FRUITS 2 100
In the above, what I want to show after executing the SQL query is
**Customer_id** **FIRST_TRANSACTION_DATE** **first_product_category** **TOTAL_QUANTITY** **TOTAL_SALES**
2 2022-07-30 VEGETABLES, FRUITS 4 350
3 2022-07-30 VEGETABLES 5 400
Customer_id 1 and 4 will not be shown as they only purchased either vegetables or fruits but not both
Check now, BTW need find logic with product_category
select CustomerId, transaction_date, product_category, quantity, sales
from(
select CustomerId, transaction_date, product_category , sum(quantity) over(partition by CustomerId ) as quantity , sum(sales) over(partition by CustomerId ) as sales, row_number() over(partition by CustomerId order by transaction_date ASC) rn
from(
select CustomerId, transaction_date, product_category, quantity, sales
from tablee t
where (product_category = 'FRUITS' and
EXISTS (select CustomerId
from tablee tt
where product_category = 'VEGETABLES'
and t.CustomerId = tt.CustomerId)) OR
(product_category = 'VEGETABLES' and
EXISTS (select CustomerId
from tablee tt
where product_category = 'FRUITS'
and t.CustomerId = tt.CustomerId)))x)over_all
where rn = 1;
HERE is FIDDLE

how to calculate Sum for two different table with different containing table field

I have two table "tbl_In_Details" and "tbl_Out_Details"
Sample data for tbl_In_Details
ID Item_Name Rate Quantity Source_company
1 wire 10 4 2020-04-21 22:47:29.083
2 Tea 4 20 2020-04-21 22:47:52.823
Sample data for tbl_Out_Details
ID Item_Name Quantity Created_Date
1 wire 1 2020-04-21 22:48:48.233
2 wire 2 2020-04-21 22:50:16.367
3 Tea 2 2020-04-21 23:48:39.943
Now i want to calculate SUM of price and price (RATE*QUANTITY) from out going table
i tried in such a way but not getting result
select o.Item_Name, SUM(o.quantity) as Total_quantity ,SUM(o.quantity * i.Rate) as Expenses
from tbl_In_Details i inner join tbl_Out_Details o
ON i.Item_Name = o.Item_Name group by o.Item_Name,o.quantity, i.Rate
My Output should be
Item_Name Total_quantity Expenses
Tea 2 8
wire 3 30
Your query is completely fine. The only thing you need to get the desired result is to delete grouping by 'quantity' and 'rate'.
select o.Item_Name, SUM(o.quantity) as Total_quantity ,SUM(o.quantity * i.Rate) as Expenses
from tbl_In_Details i inner join tbl_Out_Details o
ON i.Item_Name = o.Item_Name group by o.Item_Name;
One method uses union all and group by:
Aggregate before joining:
select i.item_name, o.quantity, i.expenses
from (select id, item_name, sum(rate*quantity) as expenses
from tbl_In_Details
group by id, item_name
) i join
(select id, item_name, sum(quantity) as quantity
from tbl_Out_Details
group by id, item_name
) o
on i.id = o.id

How to sum and subtract values using update with group by Sql query?

MyTable:
item_name Qty item_area
Belts 2 India
Shoes 20 US
T-Shirt 10 India
T-Shirt 12 US
T-Shirt 25 US
I get this by select group by query
SELECT item_name, Sum(item_qty) as Qty, item_area
FROM dbo.item_stocks
group by item_area, item_name
and my output is below:
item_name Qty item_area
Belts 2 India
Shoes 20 US
T-Shirt 10 India
T-Shirt 37 US
Now i need to subtract and update .How can i do this ?
For eg. i want to subtract 5 T-Shirt ,it will update in MyTable?
T-shirt=37-5=32
how can i update in MyTable?
You can try to use ROW_NUMBER window function to choose any one row to subtract.
;WITH CTE AS (
SELECT *,ROW_NUMBER() over(PARTITION BY item_name,item_area order by Qty desc)rn
FROM item_stocks
)
update CTE
set Qty = Qty - 5
where rn = 1 and item_name = 'T-Shirt' and item_area = 'US'
SELECT item_name, Sum(Qty) as Qty, item_area
FROM item_stocks
group by item_area, item_name
just add a column which denotes in/Out, say INOUT
don't update row, just add new row for the stock sale.
Here,
INOUT = 1 denotes IN and 2 denotes OUT
table structure like
item_name Qty item_area INOUT
Belts 2 India 1
Shoes 20 US 1
T-Shirt 10 India 1
T-Shirt 12 US 1
T-Shirt 25 US 1
T-Shirt 5 US 2
now your query looks like that
SELECT item_name,
Sum(case when INOUT = 1 then item_qty else (0-item_qty) end) as Qty,
item_area
FROM dbo.item_stocks
group by item_area, item_name

Min per group in SQL but with a caveat

I've got this table in SQL below and I need to return "the car vendors that will never be used if the car purchaser is a rational person" or "The vendor for which all car prices are more expensive then others". I've tried to do the idea of joining with itself but I am unable to get it work. The resulting output should be vendor 3 since its price for car 3 and 4 is more expensive than the other option.
id car_vendor_id vendor_name car_id price
---------------------------------------------
1 1 Vendor 1 1 25000
2 1 Vendor 1 2 40000
3 2 Vendor 2 2 35000
4 2 Vendor 2 3 25000
5 3 Vendor 3 3 28000
6 3 Vendor 3 4 40000
7 4 Vendor 4 4 35000
8 4 Vendor 4 5 20000
9 5 Vendor 5 5 18000
10 5 Vendor 5 6 32000
11 6 Vendor 6 6 30000
12 6 Vendor 6 7 20000
One method is row_number() and aggregation:
select car_vendor_id, vendor_name
from (select t.*,
rank() over (partition by car_id order by price) as seqnum
from t
) t
group by car_vendor_id, vendor_name
having min(seqnum) > 1;
The having clause is selecting rows where the vendor has no cars that are "first" based on price.
The following query uses a CTE to work out the price order for each car, so the most expensive is 1.
It then excludes rows where there is a row for the vendor where they are not the most expensive, and lastly checks they are are not the only vendor for a car.
declare #Car table(Vendor int, Car int, Price int)
insert #Car values (1,1,25000),(1,2,40000),(2,2,35000),(2,3,25000),(3,3,28000),(3,4,40000),(4,4,35000),(4,5,20000),(5,5,18000),(5,6,32000),(6,6,30000),(6,7,20000)
;with Price as (
select *, row_number() over(partition by Car order by Price desc) as r from #Car Car
)
select * from Price
where not exists(select * from Price p2 where p2.Vendor=Price.Vendor and p2.r>1)
and Vendor not in (
select Vendor from #Car where Car in (select Car from #Car group by Car having count(*)=1)
)
Check on the next query:
declare #car table(Vendor int, Car int, Price int);
insert #car
values
(1,1,25000),(1,2,40000),(2,2,35000),(2,3,25000),
(3,3,28000),(3,4,40000),(4,4,35000),(4,5,20000),
(5,5,18000),(5,6,32000),(6,6,30000),(6,7,20000);
with
a as (
select
vendor, price,
count(*) over(partition by car) cq,
count(*) over(partition by vendor) vcq,
max(price) over(partition by car) xcp
from #car
)
select vendor
from a
where cq > 1 and xcp = price
group by vendor, vcq
having count(*) = vcq;
To try the query online, please click here.

How to Retrieve Maximum Value of Each Group? - SQL

There is a table tbl_products that contains data as shown below:
Id Name
----------
1 P1
2 P2
3 P3
4 P4
5 P5
6 P6
And another table tbl_inputs that contains data as shown below:
Id Product_Id Price Register_Date
----------------------------------------
1 1 10 2010-01-01
2 1 20 2010-10-11
3 1 30 2011-01-01
4 2 100 2010-01-01
5 2 200 2009-01-01
6 3 500 2011-01-01
7 3 270 2010-10-15
8 4 80 2010-01-01
9 4 50 2010-02-02
10 4 92 2011-01-01
I want to select all products(id, name, price, register_date) with maximum date in each group.
For Example:
Id Name Price Register_Date
----------------------------------------
3 P1 30 2011-01-01
4 P2 100 2010-01-01
6 P3 500 2011-01-01
10 P4 92 2011-01-01
select
id
,name
,code
,price
from tbl_products tp
cross apply (
select top 1 price
from tbl_inputs ti
where ti.product_id = tp.id
order by register_date desc
) tii
Although is not the optimum way you can do it like:
;with gb as (
select
distinct
product_id
,max(register_date) As max_register_date
from tbl_inputs
group by product_id
)
select
id
,product_id
,price
,register_date
from tbl_inputs ti
join gb
on ti.product_id=gb.product_id
and ti.register_date = gb.max_register_date
But as I said earlier .. this is not the way to go in this case.
;with cte as
(
select t1.id, t1.name, t1.code, t2.price, t2.register_date,
row_number() over (partition by product_id order by register_date desc) rn
from tbl_products t1
join tbl_inputs t2
on t1.id = t2.product_id
)
select id, name, code, price, register_date
from cte
where rn = 1
Something like this..
select id, product_id, price, max(register_date)
from tbl_inputs
group by id, product_id, price
you can use the max function and the group by clause. if you only need results from the table tbl_inputs you even don't need a join
select product_id, max(register_date), price
from tbl_inputs
group by product_id, price
if you need field from the tbl_prducts you have to use a join.
select p.name, p. code, i.id, i.price, max(i.register_date)
from tbl_products p join tbl_inputs i on p.id=i.product_id
grooup by p.name, p. code, i.id, i.price
Try this:
SELECT id, product_id, price, register_date
FROM tbl_inputs T1 INNER JOIN
(
SELECT product_id, MAX(register_date) As Max_register_date
FROM tbl_inputs
GROUP BY product_id
) T2 ON(T1.product_id= T2.product_id AND T1.register_date= T2.Max_register_date)
This is, of course, assuming your dates are unique. if they are not, you need to add the DISTINCT Keyword to the outer SELECT statement.
edit
Sorry, I didn't explain it very well. Your dates can be duplicated, it's not a problem as long as they are unique per product id. if you can have duplicated dates per product id, then you will have more then one row per product in the outcome of the select statement I suggested, and you will have to find a way to reduce it to one row per product.
i.e:
If you have records like that (when the last date for a product appears more then once in your table with different prices)
id | product_Id | price | register_date
--------------------------------------------
1 | 1 | 10.00 | 01/01/2000
2 | 1 | 20.00 | 01/01/2000
it will result in having both of these records as outcome.
However, if the register_date is unique per product id, then you will get only one result for each product id.