Insert Data if not exists (from 2 tables) and Update otherwise - sql

Good day. I have 3 tables:
tblWarehouseProducts:
ProductID
ProductName
ProductCode
Quantity
tblBranchProducts:
ProductID
ProductCode
ProductCode
Quantity
Location
tblStockMoves:
ProductID
DestinationLocation
Quantity
ReferenceNumber
Basically, the process is that Branch X requests a product from Warehouse Y. Warehouse Y then creates a request order(called a Stock Move) and stores the request in tblStockMove.
Say for this case, we have a Stock Move with Reference Number XYZ:
REFERENCE NO. | PRODUCT ID | DESTINATION | QTY |
XYZ | 1 | BRANCH Y | 5 |
XYZ | 2 | BRANCH Y | 6 |
(where ProductID 1 is Coke and ProductID 2 is Pepsi.) Branch X on the other hand has this product on stock:
PRODUCT ID | PRODUCT NAME | PRODUCT CODE | QUANTITY | LOCATION |
1 | COKE | ABC123 | 6 | Branch X |
I am currently trying to check if the items from tblStockMoves exist in tblBranchProducts.
If Product 1 exists, it will add the Qty from tblStockMoves to the current Qty in tblBranchProducts. Product 2 will be added as a new entry since it is a new item.
I am using this query below but so far, all it does is update the stock of ProductID 1 while ignoring (not inserting) Product ID 2.
IF EXISTS (select ProductID, Location
from tblBranchProducts a
where Location = 'Branch X'
and a.ProductID in (select b.ProductID
from tblStockMoves b
where b.ReferenceNumber = 'XYZ'
and b.DestinationLocation = 'Branch X'))
BEGIN
UPDATE tblBranchProducts
SET Quantity = a.Quantity + b.Quantity
FROM tblBranchProducts a
INNER JOIN tblStockMoves b ON a.ProductID = b.ProductID
WHERE
b.ReferenceNumber = 'XYZ'
AND b.DestinationLocation = 'Branch X'
END
ELSE
BEGIN
INSERT INTO tblBranchProducts (ProductID, ProductName, ProductCode, Quantity, Location)
SELECT
b.ProductID, a.ProductName, a.ProductCode, b.Quantity, b.DestinationLocation
FROM
tblStockMoves b
INNER JOIN
tblWarehouseProducts a ON b.ProductID = a.ProductID
WHERE
b.ReferenceNumber = 'XYZ'
AND b.DestinationLocation = 'Branch X'
Other details such as Product Name and Product Code are pulled from tblWarehouseProducts and then inserted to tblBranchProducts.
Can anyone tell me why my query only updates the existing stock of Product 1 and not inserting Product 2?
Your answers are deeply appreciated!

You can do it dynamically for all products with out IF's , just addthe conditions required:
/*will insert all the unmatched products*/
INSERT INTO tblBranchProducts (ProductID, ProductName, ProductCode, Quantity, Location)
SELECT b.ProductID, a.ProductName, a.ProductCode, b.Quantity, b.DestinationLocation
FROM tblStockMoves b
inner join tblWarehouseProducts a on b.ProductID = a.ProductID
LEFT JOIN tblBranchProducts c ON(a.productid = b.productid)
where c.productid is null
And:
/*will update all the matching products*/
update tblBranchProducts a
INNER join tblStockMoves b on a.productid = b.productid
set a.quantity= b.qty

Related

JOIN Products that are IN another table

I tried to join some Products based on if they're in a table or not. I'm using MSSQL and I'm trying to do this to see if the category has some products.
simplified Query:
SELECT c.CategoryID, c.Name, p.ProductID
FROM Category AS c
JOIN Product AS p ON p.ProductID IN (
SELECT PrductID FROM exampleTable
)
ProductTable:
ProductID
CategoryID
1
1
2
1
3
2
4
4
The output I receive:
CategoryID
Name
ProductID
1
Cat1
1
1
Cat1
2
2
Cat2
3
4
Cat4
4
The expected output:
CategoryID
Name
ProductID
1
Cat1
1
2
Cat2
3
4
Cat4
4
I'm trying to only join a product if it's in the select statement and not join all products which have the same category id.
In pseudo code I'm trying to achive this:
JOIN Product AS p IF p.ProductID IN (Subquery)
Is this somehow possible?
Ed banga's answer is IMHO more elegant and perfoment but to be closer to what you proposed in your question, you can simply use a where clause.
SELECT c.CategoryID, c.Name, p.ProductID
FROM Category AS c
JOIN Product AS p ON p.CategoryID = c.CategoryID
WHERE p.ProductID IN (
SELECT PrductID FROM exampleTable
)

Write Sql script to fetch data in one to many relationship

I want to write a sql script which fetches data from 2 tables one is parent and second is child table
Bid
BidId | Code | Date
1 | H | 2022-05-12
2 | B | 2022-05-13
BidResult
BidResultId | BidId | Emi
12 | 1 | 50
13 | 1 | 20
14 | 2 | 30
Bid and BidResult
i want fetch column Date,Code,BidId from Bid Table
and BidResultId, EMI from BidResult but want a another column of Minimum EMI
from above example i want to fetch for bidId 1
Code H,date 2022-05-12,BidResultId 12, Emi 50 and Min Emi between 50 and 20 which is 20
so i have written following query
Select B.BidId,BR.EMI As Installment,
(Select Min(BR.EMI ) from BidResult BR
Inner Join Bid B on B.BidId = BR.BidResultId
where B.BidId = 5) As MinInstallment,
B.Code,
BR.BidResultId,
CONVERT(DATE, B.Date) As BidDate
from Bid B
Inner Join BidResult BR On B.BidId = BR.BidId
where B.BidId= 5 and B.TypeId = 1
All Field are starightforward except the minimum EMI value from BidResult for that BidId
please check the query and suggest if any modifications
Solution 1: With group by
select BID, min(EMI) EMI
into #temp
from BIDResult
group by BID
select b.Date, b.Code, b.BidId, br.BidResultId, br.EMI
from BID b
inner join #temp on t.BID = b.BID
inner join BIDResult br on br.BID = t.BID and br.EMI = t.EMI
Solution 2: Without group by
select *, ROW_Number() over(PARTITION by BID order by EMI) RowNumber
into #temp
from BIDResult
select b.Date, b.Code, b.BidId, br.BidResultId, br.EMI
from BID b
inner join #temp t on t.BID = b.BID and t.RowNumber = 1

Exclusive Disjunction

I have a table with product prices. There are two price types: A = offer price, B = standard price. Example:
product_id | price | price_type
-------------------------------------
001 | 0.99 | A
001 | 1.49 | B
I'm looking for a SELECT-statement that returns
the standard price (type B), if there's no offer price (type A) for this product,
the offer price (type A) whenever the product has a price of type A (disregarded if a price of type B is maintained or not).
For my example data above the statement has to return the offer price = 0.99 = type A.
This can be done with a left join. I am assuming that you will at least always have a standard price row for a product.
select p1.product_id,
coalesce(p2.price, p1.price) as price
from product_prices p1
left join product_prices p2
on p2.product_id = p1.product_id
and p2.price_type = 'A'
where p1.price_type = 'B'
You could left join two queries on the table and use coalesce to determine if there's an offer or not:
SELECT b.product_id, COALESCE(a.price, b.price)
FROM (SELECT product_id, price
FROM products
WHERE price_type = 'B') b
LEFT JOIN (SELECT product_id, price
FROM products
WHERE price_type = 'A') a ON a.product_id = b.product_id
Based on your example, it could be done by:
select *
from product
where price_type in (select min(price_type)
from product group by product_id);

SQL Construction Error

TABLE : ITEMS
---------------------------------------
Item_ID Description
---------------------------------------
1 Vivel Satin Soap
2 Flake
3 Maggie
4 Mango Juice
---------------------------------------
TABLE : SALES
------------------------------------------------
Sale_ID Sale_Date Item_ID Quantity
------------------------------------------------
1 15-Feb-14 1 2
2 16-Feb-14 1 1
3 16-Feb-14 2 1
4 17-Feb-14 3 1
5 18-Feb-14 1 1
6 18-Feb-14 2 2
------------------------------------------------
I'm having trouble in constructing SQL query as the way i wanted.... Here, i have two
tables in the database as shown above. The "ITEMS" table is for Items' Description Look-up
and "SALES" table for Items' Sale Record Look-up. Now, my requirement is, i want to select a records
from both the tables to generate report (as shown in the following). Report should contain
Items Description and its corresponding Sum of Quantity.
REPORT
------------------------------------------------------
Item_ID Description Total_Quantity
------------------------------------------------------
1 Vivel Satin Soap 4
2 Flake 3
3 Maggie 1
4 Mango Juice (SHOULD BE NULL HERE)
------------------------------------------------------
I tried following SQL query and some more to generate the report but had a logical error....
so, help me to construct better!
1) SELECT I.Item_ID, I.Description, Sum(S.Quantity)
FROM ITEMS I
INNER JOIN SALES S ON I.Item_ID = S.Item_ID
ORDER BY I.Item_ID;
2) Select I.Item_ID, I.Description, Sum(S.Quantity)
From ITEMS I, SALES S
Where S.Item_ID IN (Select Item_ID from ITEMS)
Order by I.Item_ID;
3) etc..........
try this,
SELECT I.Description, Sum(S.Quantity)
FROM ITEMS I
LEFT JOIN SALES S ON I.Item_ID = S.Item_ID
GROUP BY I.Description
Instead of Inner just try with Left Join...
And you need to use Group by Clause
SELECT I.Item_ID, I.Description, Sum(S.Quantity) -- It will return Null for Mango Juice
FROM ITEMS I
LEFT JOIN SALES S ON I.Item_ID = S.Item_ID
Group By I.Item_ID, I.Description
ORDER BY I.Item_ID;
OR:
SELECT I.Item_ID, I.Description, CASE WHEN Sum(S.Quantity) IS NULL THEN 0 ELSE Sum(S.Quantity) END Quantity -- It will return 0 for Mango Juice
FROM ITEMS I
LEFT JOIN SALES S ON I.Item_ID = S.Item_ID
Group By I.Item_ID, I.Description
ORDER BY I.Item_ID;

SELECT Statement using INTERSECT

I have two tables: tblProduct which has list of Products, and tblConsumer which has consumer name with consumed product ID.
Now I need to find the name of consumers who have consumed all products from the product table.
I tried to solve this with using INTERSECT, but the problem is I have provide each productid in WHERE clause. This syntax gives the result that I wanted, but how do I write this query where I don’t need to specify each productID.
SELECT ConsumerName FROM tblConsumer WHERE ProductID= 1
INTERSECT
SELECT ConsumerName FROM tblConsumer WHERE ProductID =2
INTERSECT
SELECT ConsumerName FROM tblConsumer WHERE ProductID =3
tblProduct
---------------------------------
ProductID | Product Name
---------------------------------
1 | Mango
2 | Orange
3 | Banana
tblConsumer
---------------------------------
ConsumerName | ProductID
---------------------------------
David | 1
David | 3
David | 2
Henry | 3
Henry | 2
If you're actually wanting to list all the Products in tblProducts, then you can use NOT EXISTS...
Otherwise, if you have a list of the Products you want to check, you can do something like:
SELECT c.ConsumerName
FROM tblConsumer AS c
WHERE c.ProductID IN (1,2,3)
GROUP BY c.ConsumerName
HAVING COUNT(DISTINCT c.ProductID) = (SELECT COUNT(DISTINCT p.ProductID) FROM tblProduct WHERE p.ProductID IN (1,2,3))
;
But I think maybe you just want to use NOT EXISTS to eliminate the Consumers for whom there's a record they haven't bought.
Like this:
SELECT *
FROM tblPerson AS pn CROSS JOIN tblProduct AS pt /* Every possible combo */
WHERE NOT EXISTS (SELECT * FROM tblConsumer c
WHERE c.ConsumerName = pn.ConsumerName
AND c.ProductID = pt.ProductID)
;
I have an other small solution:
SELECT * FROM tblConsumer
WHERE NOT EXISTS (SELECT * FROM tblProduct
LEFT JOIN tblConsumer C ON tblProduct.ProductID = C.ProductID AND tblConsumer .ConsumerName = C.ConsumerName
WHERE C.ConsumerName IS NULL)
It will work if you add a new entry too. It just checks, that is there any record, where you cant make a connection between the given Consumer and a Product.