SQL nested SELECT with JOIN - sql

I wasted all the day on one query without success , SOS I need a help :) with a given #CustomerId , I need to query all the Products that linked to customer seller can sell but not sold to him before , the Commissions table is indication of what products seller can sell
Thanks in advance

SELECT sellableProduct
FROM (SELECT Comissions.ProductId AS sellableProduct, Sellers.SellerId AS sellableSeller FROM Comissions INNER JOIN Sellers ON Comissions.SellerId=Sellers.SellerId INNER JOIN Customers ON Sellers.SellerId=Customers.SellerId WHERE Customers.CustomerId = #customerid) AS tblSellable
LEFT JOIN (SELECT Sales.ProductId AS soldProduct, Customers.SellerId as soldSeller FROM Customers INNER JOIN Sales ON Customers.CustomerId=Sales.CustomerId WHERE Customers.CustomerId = #customerid) AS tblSold
ON tblSellable.sellableProduct=tblSold.soldProduct AND tblSellable.sellableSeller=tblSold.soldSeller
WHERE tblSold.soldProduct IS NULL
this way you avoid time-consuming IN statements
If a Customer can only have one Seller, then you can omit the seller link:
SELECT sellableProduct
FROM (SELECT Comissions.ProductId AS sellableProduct FROM Comissions INNER JOIN Sellers ON Comissions.SellerId=Sellers.SellerId INNER JOIN Customers ON Sellers.SellerId=Customers.SellerId WHERE Customers.CustomerId = #customerid) AS tblSellable
LEFT JOIN (SELECT Sales.ProductId AS soldProduct FROM Sales WHERE Sales.CustomerId = #customerid) AS tblSold
ON tblSellable.sellableProduct=tblSold.soldProduct
WHERE tblSold.soldProduct IS NULL

Basically, you're looking for products that have a record in commissions, but not in sales. Using :id to denote the specific ID:
SELECT *
FROM products
WHERE productid IN (SELECT productid
FROM commissions
WHERE sellerid = :id) AND
productid NOT IN (SELECT productid
FROM sales
JOIN customers ON sales.customerid = cusomers.customerid
WHERE sellerid = :id)

Would this work?
SELECT sell.*, prod.* FROM
Sellers sell
INNER JOIN Customers cust ON cust.SellerId = sell.SellerId
LEFT JOIN Commissions comm ON sell.SellerId = comm.SellerId
LEFT JOIN Products prod ON prod.ProductId = comm.ProductId
WHERE prod.ProductId NOT IN (
SELECT ProductId
FROM Products p INNER JOIN
Sales s ON s.ProductId = p.ProductId
WHERE s.CustomerId = #CustomerId
It get all the sellers and the respective product from commission, where the product Id is NOT associated with any sale of the client

Related

SQL Server stored procedure query multiple tables

I am querying a SQL Server database using a stored procedure.
My database tables include:
Customers
SalesOrders - Linked to the customers with an id
SalesOrderLines - Linked to the SalesOrders with an id
SalesOrderReleases - Linked to the SalesOrderLines with an id, stores the quantity on the order line that has been released and ready to manufacture, the SalesOrderLine quantity can be all on one release or split up on multiple
FinishedGoods - linked to the SalesOrderLines with an id, stores the quantity of the SalesOrderLine where manufacturing is complete, the SalesOrderLine quantity can be all on one FinishedGood entry or split up on multiple
I need to retrieve all the customers that have SalesOrderLines with SalesOrderReleases and FinishedGoods where the total quantity finished is less than the total quantity released
I have tried this SQL code but Customers appear repeatedly in the results
SELECT
Customer.ID, Customer.Name
FROM
Customer
INNER JOIN
SalesOrder ON Customer.ID = SalesOrder.CustomerID
INNER JOIN
SalesOrderLine ON SalesOrder.ID = SalesOrderLine.SalesOrderID
INNER JOIN
SalesOrderRelease ON SalesOrderLine.ID = SalesOrderRelease.SalesOrderLineID
INNER JOIN
FinishedGood ON SalesOrderLine.ID = FinishedGood.SalesOrderLineID AND FinishedGood.Quantity < SalesOrderRelease.Quantity
I am looking for a SQL code snippet that will query multiple tables the way I have described.
try this code:
SELECT Customer.ID, Customer.Name FROM Customer
INNER JOIN SalesOrder ON Customer.ID = Order.CustomerID
INNER JOIN SalesOrderLine ON Order.ID = OrderLine.OrderID
INNER JOIN
(SELECT OrderID, OrderLineID, SUM (Quantity) AS SRQuantity FROM
SalesOrderRelease GROUP BY OrderID, OrderLineID) AS SRQ
ON SRQ.OrderID = SalesOrderLine.OrderID
INNER JOIN
(SELECT OrderLineID, SUM (Quantity) AS FGQuantity FROM
FinishedGoods GROUP BY OrderLineID) AS FGQ
ON SRQ.OrderLineID = FGQ.OrderLineID
WHERE FGQ.FgQuantity < SRQ.SRQuantity
Credits to Sergey for his answer, I was able to use the sample code he provided with several slight modifications:
SELECT Customer.ID, Customer.Name FROM Customer
INNER JOIN SalesOrder ON Customer.ID = SalesOrder.CustomerID
INNER JOIN SalesOrderLine ON SalesOrder.ID = SalesOrderLine.SalesOrderID
INNER JOIN
(SELECT SalesOrderID, SalesOrderLineID, SUM (Quantity) AS SRQuantity FROM
SalesOrderRelease GROUP BY SalesOrderID, SalesOrderLineID) AS SRQ
ON SRQ.SalesOrderLineID = SalesOrderLine.SalesOrderID
LEFT JOIN
(SELECT SalesOrderLineID, SUM (Quantity) AS FGQuantity FROM
FinishedGood GROUP BY SalesOrderLineID) AS FGQ
ON SRQ.SalesOrderLineID = FGQ.SalesOrderLineID
WHERE ISNULL(FGQ.FgQuantity, 0) < SRQ.SRQuantity
The last join needed to be a Left Join
When comparing the FgQuantity and the SRQuantity in the last line, I needed to have it check for NULL values
With these modifications everythings works perfectly!

Customer product sale query incorrect result in sql server 2016

My DDL looks like below:
CREATE TABLE CUSTOMER
(
ID INT PRIMARY KEY,
CUSTOMER_NAME VARCHAR(50),
CITY_ID INT,
)
CREATE TABLE product
(
id int,
sku VARCHAR(50),
product_name varchar(100),
stock_qty int
)
create table Invoice
(
id int,
invoice_number varchar(100),
customer_id int
)
CREATE TABLE Invoice_item
(
id int,
invoice_id int,
product_id int,
quantity decimal(5,2),
price decimal(5,2),
line_total_price decimal(5,2)
)
I am trying to get sales details of all customer and products
output should return all customer even customer without invoices and
also all product even those product that were not sold.
I need to print customer even not have invoice and even those product
that were not sold
than customer and product as NA and quantity as o
Code i have written:
SELECT ISNULL(c.customer_name,'N/A')AS customer_name,ISNULL(p.product_name,'N/A') AS product_name,
sum(ISNULL(invitm.quantity,'0')) as quantity
FROM customer as c left outer join product as p
on c.id = p.id
left outer join invoice as inv on c.id = inv.id
left outer join invoice_item as invitm on c.id = invitm.id
group by c.customer_name,p.product_name
But this is giving incorrect result. am i doing any mistake with join. please share your suggestion
If you want all customer and product combinations, then I would suggest:
select c.customer_name, p.product_name,
coalesce(sum(ii.quantity), 0) as quantity
from customer c cross join
product p left join
invoice i
on c.id = i.customer_id left join
invoice_item ii
on ii.invoice_id = i.id and ii.product_id = p.id
group by c.customer_name, p.product_name;
If you want all customer/product combinations that exist and then extras for the customers and products that don't exist, I would suggest union all:
select c.customer_name, p.product_name,
coalesce(sum(ii.quantity), 0) as quantity
from invoice i join
customer c
on c.id = i.customer_id join
invoice_item ii
on ii.invoice_id = i.id join
product p
on ii.product_id = p.id
group by c.customer_name, p.product_name
union all
select c.customer_name, null, 0
from customer c
where not exists (select 1 from invoice i where i.customer_id = c.id)
union all
select null, p.product_name, 0
from product p
where not exists (select 1 from invoice_item ii where ii.product_id = p.id);
Maybe like this (I have not checked syntax) - all your joins were totally wrong; you need to join on corresponding fields (foreign keys), not on id-s:
SELECT ISNULL(c.customer_name,'N/A')AS customer_name,ISNULL(p.product_name,'N/A') AS product_name,
sum(ISNULL(invitm.quantity,'0')) as quantity
FROM customer as c full outer join product as p
on c.product_id = p.id
left outer join invoice as inv on c.id = inv.customer_id
left outer join invoice_item as invitm on invitm.invoice_id = inv.id and invitm.product_id = p.id
group by c.customer_name,p.product_name
This is actually a interview question. Below query might be correct:
SELECT c.customer_name,
p.product_name,
Coalesce((ii.quantity), 0) AS quantity
FROM customer c
LEFT JOIN invoice i
on c.id = i.customer_id
LEFT JOIN invoice_item ii
ON ii.invoice_id = i.id
LEFT JOIN product p
ON ii.product_id = p.id
ORDER BY c.customerid,
p.product_id,
ii.id
UNION
SELECT 'N/A',
p.product_name,
0
FROM products p ORDER p.id

Joining 2 Many-To-Many Relationship Tables

Problem:
Find the net balance of the total order amount and total payments for each customer.
There are 4 tables involved: OrderDetails, Orders, Payments and Customer.
The total amount order = quantity order * price each [in OrderDetails]
The total payment = sum of different payments for the same order.
Customers are linked to Payments and Orders with CustomerNumber. Orders are linked to OrderDetails with OrderNumber.
I tried joining the 4 tables with the INNER JOIN function.
SELECT
c.customername,
SUM(od.quantityordered * od.priceeach) - SUM(p.amount) AS Net_Balance
FROM
(
(
orderdetails od
INNER JOIN orders o ON od.ordernumber = o.ordernumber
)
INNER JOIN customers c ON o.customernumber = c.customernumber
)
INNER JOIN payments p ON c.customernumber = p.customernumber
GROUP BY c.customername;
The expected results should be 0 for almost every customers.
However, what I have got is the total amount order and total payment are multiplied by some constants. Specifically, the total payment shown is multiplied by the number of payments for each order.
Anybody have any ideas to save my life?
This is a typical issue when dealing with N-M relationships. To solve it, one solution is to move the aggregation to subqueries:
SELECT c.customername, o.amt - p.amt AS Net_Balance
FROM customers c
INNER JOIN (
SELECT ord.customernumber, SUM(det.quantityordered * det.priceeach) as amt
FROM orders ord
INNER JOIN orderdetails det ON ord.ordernumber = det.ordernumber
GROUP BY ord.customernumber
) o ON o.customernumber = c.customernumber
INNER JOIN (
SELECT customernumber, SUM(amount) as amt
FROM payments
GROUP BY customernumber
) p ON p.customernumber = c.customernumber
SELECT c.customername, SUM(od.quantityordered*od.priceeach) as ordersum , SUM(p.amount) as paymentsum'
What's the result of the two columns ?
Is it what you want?

sql get newest date and price of all inventory_items

I have this sql tables, and i need to get from all inventory items the newest date from table: orders with the price paid on this date
table:orders
id
date
table:order_items
order_id
inventory_id
price
table:inventory
item_number
if i do something like that:
SELECT inventory.item_number, orders.date, order_items.price
FROM inventory
INNER JOIN order_items ON inventory.id = order_items.inventory_id
INNER JOIN orders ON order_items.order_id = orders.id
WHERE max(orders.date)
it's not working, and i get an error.
What is the correct way to do that
You need a where clause, but the MAX() cannot go there directly. Try a subquery:
SELECT i.item_number, o.date, orders.price
FROM inventory i INNER JOIN
order_items oi
ON i.id = oi.inventory_id INNER JOIN
orders o
ON oi.order_id = o.id
WHERE o.date = (SELECt max(o2.date) FROM orders o2);

Joining on a group by

Lets say that I have three tables, customers, orders and orderDetails.
I'm doing this:
SELECT orders.ordersId, sum(orderDetails.total)
FROM orders
LEFT OUTER JOIN orderDetails ON orders.ordersId = orderDetails.ordersId
GROUP BY orders.ordersId
But lets say the orders table contains customersId. How do I join on the customers table so that I can also add the customer's name to the fields selected?
Thanks,
Barry
SELECT orders.ordersId, sum(orderDetails.total), customer.name
FROM orders
LEFT OUTER JOIN orderDetails ON orders.ordersId = orderDetails.ordersId
LEFT OUTER JOIN customer on customer.customerid = orders.customerid
GROUP BY orders.ordersId , customer.name
Try that out or something similar.
you can do it this way, which will let you get more than customer name if needed:
SELECT o.ordersId, o.orderTotal, c.customername, c.(other customer data)
FROM
(
SELECT orders.ordersId
, sum(orderDetails.total) as orderTotal
, orders.customersid
FROM orders
LEFT OUTER JOIN orderDetails
ON orders.ordersId = orderDetails.ordersId
GROUP BY orders.ordersId, orders.customersid
) o
LEFT JOIN customers c
ON o.customersid = c.customersid