stock query not show exact result - sql

I use this query to maintain my stock but its not show exact result
select p.Product_Name Product
,isnull(sum(d.qty),0) Purchase_Qty
,isnull(sum(i.qty),0) Issue_Qty
,(isnull(sum(d.qty),0)-isnull(sum(i.qty),0)) InStock
from purchase_dtl d
left join issue_dpt i on i.Product_ID=d.Product_ID
right join product p on p.id = d.Product_ID
group by Product_Name
Query result
Product | Purchase_Qty | Issue_Qty | InStock
---------------------------------------------
Pen 1000 300 700
Books 4000 1000 3000
My exact purchase qty
Product | Purchase_Qty
----------------------
Pen 500
Books 2000
My exact issue qty
Product | Issue_Qty
-------------------
Pen 300
Books 1000
Please help me to solve my problem
Thanks

select p.Product_Name Product
, p.Purchase_Qty
, isnull(sum(i.qty),0) Issue_Qty
, p.Purchase_Qty-isnull(sum(i.qty),0) InStock
from (select p.id, p.Product_Name, isnull(sum(d.qty),0) Purchase_Qty
from product p left join purchase_dtl d on p.id = d.Product_ID
group by p.id, p.Product_Name) p
left join issue_dpt i on i.Product_ID = p.id
group by Product_Name, p.Purchase_Qty
I suppose joining purchase_dtl and issue_dpt gives you some extra rows for Purchase_Qty
Join product with purchase_dtl first to calculate the aggregate data and then join again with issue_dpt

Related

How to retrieve unpaid amount of each invoice for finance charges?

I am working on implementing finance charges, but don't know how to retrieve the unpaid amount of each invoice. I am not new to SQL, however this problem has me stumped. Forgive me if I just didn't search properly.
So, let us say I have an invoice table:
id | amount
----+--------------
1 | 50.00
2 | 50.00
3 | 50.00
4 | 50.00
5 | 50.00
And a payments table:
amount
--------------
50.00
25.00
The result set should be this:
invoice_id | unpaid_amount
------------+--------------
2 | 25.00
3 | 50.00
4 | 50.00
5 | 50.00
Of course, there is quite a bit more to add to implement finance charges, but I think I can get the rest.
Edit: Sorry, an oversight of mine. The id's are not related. Removed payment id column.
Edit 2: These are fictual numbers, the real life numbers will be anything, so no matches can be made on the amounts.
Edit 3: And here I have created a SQL Fiddle to show what I have so far, based on #GordonLinoff second answer. I would appreciate a cleaner approach than the kludgy SQL I concocted.
I think you want a join:
select i.id as invoice_id,
(i.amount - coalesce(p.amount, 0)) as net_amount
from invoice i left join
payment p
on i.id = p.id;
EDIT:
Or, you may want:
select i.*,
(case when sum(i.amount) over (order by i.id) < p.amount
then i.amount
else greatest(p.amount - sum(i.amount) over (order by i.id) + i.amount, 0)
end) as amount_paid
from invoice i cross join
(select sum(amount) as amount
from payment
) p;
Here is a db<>fiddle.
You can do by using LEFT JOIN and subtract amounts from both table. COALSECE is here to prevent you from getting NULL when there is no payment.
select
i.id as invoice_id
,i.amount - coalesce(p.amount,0) as amount
from invoice i
left join payments p
on p.id = i.id
If in your payments talbe can be more than one payment for an invoice you should group payments before joining it to invoice.
select
i.id as invoice_id
,i.amount - coalesce(p.amount,0) as amount
from invoice i
left join (select id, sum(amount) as amount from payments group by id) p
on p.id = i.id

Select query where column does not equal column in different table in SQL Server

I have two different tables that contain order/pricing data. The first table, Orders, has columns order, item and price. The second table, Pricing has columns item, price, and effective date. I want to find all orders where orders.price <> pricing.price where effective date = 7/27/2017.
Orders:
Order Item Price
---------------------
1 ABC 12.50
2 ABC 12.00
3 ABC 11.50
4 XYZ 20.00
Pricing:
Item Price Effective Date
-------------------------------
ABC 12.50 7/27/2017
ABC 12.00 12/1/2016
ABC 11.50 12/1/2015
XYZ 25.00 7/27/2017
XYZ 20.00 12/1/2016
I want the query to tell me that order 2,3,4 do not have the most up to date pricing.
Please advise.
SELECT O.ORDER, (P.PRICE - O.PRICE) AS 'Variance'
FROM ORDERS O, PRICING P
WHERE O.ITEM = P.ITEM
AND P.[EFFECTIVE DATE] = '7/27/2017'
AND P.PRICE <> O.PRICE
ORDER BY O.ORDER ASC
It should be like this:-
SELECT * FROM Orders O
INNER JOIN Pricing P ON O.Item = P.Item
Where O.Price != P.Price AND [Effective Date] ='07/27/2017'
Are you looking for something like this?
SELECT o.[Order]
FROM Orders o JOIN Pricing p
ON o.Item = p.Item
AND p.Effective_Date = '2017-07-27'
AND o.price <> p.price
SQLFiddle demo
Output:
| Order |
|-------|
| 2 |
| 3 |
| 4 |
select o.order,o.Item,o.price from orders o inner join
pricing on o.item=pricing.item
where o.price <>(select p.price from pricing p where p.effectivedate = '2017-07-27' and p.item=o.item)

Completing a table with rows not existing

I have a table like this:
buyer product quantity
tom skirt 2
anna skirt 3
tom jeans 5
The distinct(product) = skirt and jeans
I want a table that inserts another column with quantity = 0 when the <buyer, product> tuple does not exist for all possible products.
So the result would be:
buyer product quantity
tom skirt 2
anna skirt 3
tom jeans 5
anna jeans 0
It does not look very complicated but I don't know how to do it.
UPDATE
I have found one extra complication.
My product is actually defined by two fields: class and product. Product can be null and I need not to lose the information quantity when the product field is null (now it is happening with the cross join).
So if I have this:
buyer class product quantity
tom clothes skirt 2
anna clothes skirt 3
tom clothes jeans 5
jim shoes NULL 7
I would need:
buyer class product quantity
tom clothes skirt 2
anna clothes skirt 3
tom clothes jeans 5
anna clothes jeans 0
jim shoes NULL 7
jim clothes skirt 0
jim clothes jeans 0
tom shoes NULL 0
anna shoes NULL 0
Thank you all, I know I am complicating things!
You can use a cross join to generate all possible combinations of buyers and products. Then use a left join (or not exists) to filter out the ones already in the table:
insert into table(buyer, product, quantity)
select b.buyer, p.product, 0
from (select distinct buyer from table) b cross join
(select distinct product p from table) p left join
table t
on t.buyer = b.buyer and t.product = p.product
where t.buyer is null;
EDIT:
If you want a query that returns all the rows, then you would use something quite similar:
select b.buyer, p.product, coalesce(t.qty, 0) as qty
from (select distinct buyer from table) b cross join
(select distinct product p from table) p left join
table t
on t.buyer = b.buyer and t.product = p.product;
EDIT II:
If you have NULL values for buyer and/or product, then use NULL safe comparisons:
select b.buyer, p.product, coalesce(t.qty, 0) as qty
from (select distinct buyer from table) b cross join
(select distinct product p from table) p left join
table t
on t.buyer is not distinct from b.buyer and
t.product is not distinct from p.product;
(As a minor side note: I really do not like the use of distinct in this construct. Why did Postgres (ANSI ?) give it such a complicated name?)
The solution of #Gordon is almost full, I edit like this:
declare #tb table (buyer varchar(150), product varchar(150), quantity int)
insert into #tb
values('tom','skirt',2),
('anna','skirt',3),
('tom','jeans',5)
select *
from #tb a
left join( select
distinct(product)
from #tb) b on a.product = a.product
select b.buyer, p.p, isnull(t.quantity,0)
from (select distinct buyer from #tb) b cross join
(select distinct product p from #tb) p left join
#tb t
on t.buyer = b.buyer and t.product = p.p
--where t.buyer is null
Try it.

SQL Sum of count across 3 tables

Say you have 3 tables:
Categories
Category ID
Name
Products
Product ID
Category ID (FK)
Sales
Product ID (FK)
Sale date
I'm trying to come up with a query that will result in a data table that shows the total number of sales per category, like:
Cat ID | Name | Total Sales
-------|------|-------------
1 | Red | 35
2 | Blue | 25
For bonus points, add a WHERE clause to select within a specific date range on the 'Sale Date' column.
I'm using SQL Server.
For SQL-Server could be something like that:
SELECT c.CategoryID AS [Cat ID],
c.Name AS [Name],
COUNT(s.ProductID) AS [Total Sales]
FROM Categories c
LEFT JOIN Products p
ON c.CategoryID = p.CategoryID
LEFT JOIN Sales s
ON p.ProductID = s.ProductID
WHERE s.Saledate BETWEEEN startDate and endDate
GROUP BY c.CategoryID, c.Name
select Categories.CatID, Categories.Name, count(*) as TotalSales
from Categories
join Products ON Categories.CategoryID = Products.CategoryID
join Sales ON Products.ProductID = Sales.ProductID
WHERE Sales.Saledate BETWEEEN date1 and date2
GROUP BY Categories.CatID, Categories.Name

How get data from 3 tables?

I have 3 tables
collecton, paymentdata, payment
Payment table is computed table and it has only one product data
So, rcvamt and restamt get from payment table
I have following data
Collection:
id(PK) clientid company Client product total note
1 2001 Company1 Client1 Product1 50000 note1
2 2002 Company2 Client2 Product2 60000 note2
3 2003 Company3 Client3 Product3 70000 note3
PaymentData:
wid(PK)wcid(FK) clientid product rcvamt restamt rcvdate nxtdate Note
1 1 2001 Product1 500 49500 10-1-2015 11-2-2015 abc1
2 1 2001 Product1 800 48700 11-2-2015 12-3-2015 xyz1
3 2 2002 Product2 1500 58500 5-3-2015 6-4-2015 qwe1
Payment
id(PK) wid(FK) clientid product rcvamt restamt
1 2 2001 Product1 1300 48700
2 3 2002 Product2 1500 58500
I want to show a report like
clientid company procudt total rcvamt restamt rcvdate nxtdate note
2001 Company1 Product1 50000 1300 48700 11-2-2015 12-3-2015 xyz1
2002 Company2 Product2 60000 1500 58500 5-3-2015 6-4-2015 qwe1
2003 Company3 Product3 70000 - - - - -
I tried to make it simple:
SELECT DISTINCT
C.clientid
, C.company
, C.product
, C.total
, P.rcvamt
, P.restamt
, ( SELECT TOP 1 rcvdate FROM PaymentData AS PD1 WHERE PD1.ClientID=PD.ClientID AND PD1.Product=PD.Product ORDER BY rcvdate DESC)
, ( SELECT TOP 1 nxtdate FROM PaymentData AS PD1 WHERE PD1.ClientID=PD.ClientID AND PD1.Product=PD.Product ORDER BY rcvdate DESC)
, ( SELECT TOP 1 Note FROM PaymentData AS PD1 WHERE PD1.ClientID=PD.ClientID AND PD1.Product=PD.Product ORDER BY rcvdate DESC)
FROM
Collection C
LEFT OUTER JOIN Payment P
ON C.clientid = P.clientid
LEFT OUTER JOIN PaymentData PD
ON P.clientid = PD.clientid
But I don't know all the relationships between the tables.
The Answer to your Question could look like this
Select Collection.clientid
,Collection.company
,Collection.product
,Collection.total
,Payment.rcvamt
,Payment.restamt
,PaymentData.rcvdate
,PaymentData.nxtdate
,PaymentData.Note
From PaymentData
Inner Join (Select wcid
,Max(PaymentData.rcvdate) as rcvdate
,Max(PaymentData.nxtdate) as nxtdate
FROM PaymentData
GROUP BY wcid) AS SubSelect ON PaymentData.wcid = SubSelect.wcid
AND PaymentData.rcvdate = SubSelect.rcvdate
AND PaymentData.nxtdate = SubSelect.nxtdate
Inner Join Payment on PaymentData.wcid = Payment.id
RIGHT OUTER JOIN Collection ON PaymentData.clientid = Collection.clientid
Here the sqlfiddle to prove my Answer.
Something like this should work. It appears you want an aggregation on the restamt, both other fields are the last payment received. I also assume this is SQL Server due to your name. If it's a different db, please provide the
UPDATE: Changed to LEFT JOIN to handle client 3 without products, fixed typo in product. SQL Fiddle: http://sqlfiddle.com/#!3/8ad566/19/0
SELECT
c.clientid,
c.company,
c.product,
c.total,
SUM(pd.rcvamt) AS rcvamt,
LastPayment.restamt,
LastPayment.rcvdate,
LastPayment.nxtDate,
LastPayment.note
FROM Collection c
LEFT OUTER JOIN PaymentData pd
ON pd.wcid = c.id
LEFT OUTER JOIN (
SELECT
wcid,
restamt,
rcvdate,
nxtdate,
Note,
ROW_NUMBER() OVER (PARTITION BY wcid ORDER BY rcvdate DESC) AS RowNum
FROM PaymentData
) LastPayment
ON LastPayment.wcid = c.id
AND LastPayment.RowNum = 1 -- Get last payment info
GROUP BY
c.clientid,
c.company,
c.product,
c.total,
LastPayment.restamt,
LastPayment.rcvdate,
LastPayment.nxtDate,
LastPayment.note
ORDER BY
c.clientid