SQL query show all IDs regardless if present or not - sql

I have a very basic SQL question. There are two tables: products and inventory. If I search on the products ID in the inventory table (using a left join shown below) I get all the product IDs (names) which have quantity in the inventory. But I would like to have shown all the product IDs and if they are not present in the inventory then have a 0 or Null as quantity.
Right now my code only shows the IDs which have quantity in the inventory table
Select A.ProductID, A.Name, B.Quantity
From Production.Product A
Left join Production.ProductInventory B
On A.ProductID = B.ProductID
Where B.LocationID = 1
Thank you for your help in advance!

You have to move predicate
B.LocationID = 1
from WHERE clause to ON:
Left join Production.ProductInventory B
On A.ProductID = B.ProductID AND B.LocationID = 1
If the predicate is in WHERE then LEFT JOIN becomes an INNER JOIN, since for NULL records the predicate will not evaluate to TRUE.
So, your query will be:
Select A.ProductID, A.Name, B.Quantity
From Production.Product A
Left join Production.ProductInventory B
On A.ProductID = B.ProductID AND B.LocationID = 1
This returns all Production.Product records. Field Quantity of Production.ProductInventory is returned by the query only when ProductID fields match and LocationID = 1, otherwise NULL is returned.

Related

list all table elements and count() even if count is 0

Suppose the following tables:
table book(
id,
title,
deleted
)
table invoice(
id,
book_id,
settled
)
I need a list off all the books and the number of settled invoices for each book.
I tried this:
select book.id, title, count(invoice.id)
from book LEFT OUTER JOIN invoice ON book.id=invoice.book_id
where deleted=0
and settled=1
group by book.id
This works only if a book has at least 1 settled invoice or if it doesn't have any invoce at all. However it fails when a book has unsettled invoices and it doesn't have any settled invoice.
Any idea how to query it ?
The following will list all books, but only join and count settled invoices.
SELECT
b.id, b.title, COUNT(i.id) AS settled
FROM
book b
LEFT JOIN invoice i
ON b.id = i.book_id
AND i.settled = 1
WHERE
b.deleted = 0
GROUP BY
b.id
The condition and settled = 1 on your WHERE is effectively turning your LEFT JOIN into an INNER JOIN. You can add a CASE expression to your COUNT:
SELECT b.id,
b.title,
COUNT(CASE WHEN i.settled = 1 THEN 1 END)
FROM book b
LEFT JOIN invoice i
ON b.id = i.book_id
WHERE b.deleted=0
GROUP BY b.id;
Or use the LEFT JOIN with the invoice table already filtered:
SELECT b.id,
b.title,
COUNT(i.id)
FROM book b
LEFT JOIN ( SELECT *
FROM invoice
WHERE settled = 1) i
ON b.id = i.book_id
WHERE b.deleted=0
GROUP BY b.id;

Update table based on a select from another

I have this select statement below which I would like to use to update the quantity of the products in another table, tablex. I cannot seem to figure out how to match the product number from this query to the productnumber tablex and then add the quantity found in this statement to the existing quantity in tablex.
select
p.ProductNumber, sod.Quantity ,so.StateCode
from
SalesOrderDetail sod
right join
ProductAssociation pa on sod.ProductId = pa.ProductId
left join
Product p on pa.AssociatedProduct = p.ProductId
left join
SalesOrder so on so.SalesOrderId = sod.SalesOrderId
where
so.StateCode = '3'
You can have update base on multiple tables, the syntax is something like
update tablex
set tablex.quantity = sod.Quantity
from tablex join product p on tablex.productnumber = p.ProductNumber
join... -- add the rest of your joins and conditions.
I'm guessing that you're trying to update a large quantity of rows in TableX so I'm going to suggest a way to do them all at once rather than one at a time.
update TableX
set quantity = quantity +
(select sod.quantity from SalesOrderDetail where sod.ProductId = TableX.ProductId)
You might wish to do this on a subset of SalesOrderDetail, and that's fine, just use the WHERE clause for that.
Try
UPDATE tablex
SET Quantity= Quantity +
(SELECT sod.Quantity FROM SalesOrderDetail sod
RIGHT JOIN ProductAssociation pa ON sod.ProductId=pa.ProductId
LEFT JOIN Product p ON pa.AssociatedProduct=p.ProductId
LEFT JOIN SalesOrder so ON so.SalesOrderId=sod.SalesOrderId
WHERE so.StateCode='3' AND p.ProductNumber=Tablex.productnumber)
Are you looking for this?
UPDATE tx SET tx.Quantity = tx.Quantity + sod.Quantity FROM
from SalesOrderDetail sod
right join ProductAssociation pa on sod.ProductId=pa.ProductId
left join Product p on pa.AssociatedProduct=p.ProductId
left join SalesOrder so on so.SalesOrderId=sod.SalesOrderId
left join tablex tx on p.ProductNumer = tx.ProductNumber
where so.StateCode='3'
How can I do an UPDATE statement with JOIN in SQL?
Basic syntax for UPDATE with a JOIN:
UPDATE A
SET A.foo = B.bar
FROM TableA A
JOIN TableB B
ON A.col1 = B.colx
So I believe you're after something like:
UPDATE A
SET A.Quantity = B.Quantity + A.Quantity
FROM Tablex A
JOIN (select p.ProductNumber, sod.Quantity ,so.StateCode
from SalesOrderDetail sod
right join ProductAssociation pa on sod.ProductId=pa.ProductId
left join Product p on pa.AssociatedProduct=p.ProductId
left join SalesOrder so on so.SalesOrderId=sod.SalesOrderId
where so.StateCode='3'
)B
ON A.ProductNumber = B.ProductNumber
Not sure how your StateCode factors in, additional JOIN criteria perhaps?

SQL Join with SUM()

I have two Tables
Product Details(About Product)
Sale Order Details(What Price is sold, quantity of products sold per order).
I am trying to do Join on Table 1 and Table 2 which should give the all the product details and sum(Quantity), Sum(Price)
Problem Facing: There are some products in Table 1 which are never sold, and those rows are missing in the result set, but I want details for all the rows in Table 1 with rows of Products never purchased should be NULL or 'o'
Query I am Using:
select
P.*,
ISNULL((sum([Q.Quantity])),0),
ISNULL((sum([Q.Price])),0)
From Table1 P
Left Outer Join Table2 Q on P.Product_ID = Q.Product_ID
Please help me with any suggestions that would work for me
How about this one:
select
P.Product_ID,
ISNULL(sum([Q.Quantity]),0),
ISNULL(sum([Q.Price]),0)
From Table1 P
Left Outer Join Table2 Q
on P.Product_ID = Q.Product_ID
group by
P.Product_Id

Using sum with a nested select

I'm using SQL Server. This statement lists my products per menu:
SELECT menuname, productname
FROM [web].[dbo].[tblMenus]
FULL OUTER JOIN [web].[dbo].[tblProductsRelMenus]
ON [tblMenus].Id = [tblProductsRelMenus].MenuId
FULL OUTER JOIN [web].[dbo].[tblProducts]
ON [tblProductsRelMenus].ProductId = [tblProducts].ProductId
LEFT JOIN [web].[dbo].[tblOrderDetails]
ON ([tblProducts].Id = [tblOrderDetails].ProductId)
GROUP BY [tblProducts].ProductName
Some products don't have menus and vice versa. I use the following to establish what has been sold of each product.
SELECT [tblProducts].ProductName, SUM([tblOrderDetails].Ammount) as amount
FROM [web].[dbo].[tblProducts]
LEFT JOIN [web].[dbo].[tblOrderDetails]
ON ([tblProducts].ProductId = [tblOrderDetails].ProductId)
GROUP BY [tblProducts].ProductName
What I want to do is complement the top table with an amount column. That is, I want a table with the same number of rows as in the first table above but with an amount value if it exists, otherwise null.
I can't figure out how to do this. Any suggestions?
If I am not missing anything, the second query could be simplified, then incorporated into the first query like this:
SELECT
m.menuname,
p.productname,
t.amount
FROM [web].[dbo].[tblMenus] m
FULL JOIN [web].[dbo].[tblProductsRelMenus] pm ON m.Id = pm.MenuId
FULL JOIN [web].[dbo].[tblProducts] p ON pm.ProductId = p.ProductId
LEFT JOIN (
SELECT ProductId, SUM(Amount) as amount
FROM [web].[dbo].[tblOrderDetails]
GROUP BY ProductId
) t ON p.ProducId = t.ProductId

Count of Detail record for a Master table

I have a Master Table and a Detail Table(like Categories and Products) in SQL server and some of the Categories Do not have Products.
I want to count Products of a Category and my Where condition is like this ProductID=100.
In Result i want to have 0 near the Categories that have not Products and the other Categories have Products count. the result must be only for ProductID=100 and the number off the Result is number off the Categories record.iwant to create a view and each time i run this query :
select * from -ViewName where ProductID=#newProductID
This could be done fairly simply in a query that doesn't use views - it would be something like:
select c.CategoryName, count(p.ProductID)
from Category c
left join Product p
on c.CategoryID = p.CategoryID and p.ProductID = 100
Note that the condition on ProductID has to be part of the join criteria, not in the where clause, otherwise the query will only return categories that include the specified product.
This could be done fairly inefficiently in a view, by using a cross join - something like:
create view vwCategoryProduct as
select c.CategoryName,
p.ProductID,
case when c.CategoryID = p.CategoryID then 1 else 0 end as ProductIncluded
from Category c
cross join Product p
- and then selecting from the view like so:
select * from vwCategoryProduct where ProductID = 100
Not sure I get you on all of that
but something like
Select Category_Name, IsNull(Count(Products.Category_ID),0)
From Categories
Outer join Products On Products.CategoryID = Categories.CategoryID
Where Products.ProductID = 100
Should get you away...
Try it this way:
select count(p.*) as 'Number of Products'
from Categories c
left outer join Products p on c.ProductID = p.ProductID and ProductID = 100