SQL Server stored procedure query multiple tables - sql

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!

Related

How to deal with complex schema in SQL database

can anyone please help to create a query for this, I tried a lot but did not succeed
create a SQL query selecting all employees, invoice totals for the customers they handle.
Assuming that a single invoice is calculated by UnitPrice * Quantity, the following query should work:
select EmployeeId, sum(invoice) InvoicesTotal
from
(select EmployeeId, SupportRepId, CustomerId
from employees e
left join customers c
on e.EmployeeId = c.SupportRepId) ec
left join
(select CustomerId, sum(UnitPrice * Quantity) invoice
from invoices i
join
invoice_items ii
on i.InvoiceId = ii.InvoiceId
group by CustomerId) ci
on
ec.CustomerId = ci.CustomerId
group by EmployeeId

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?

Complex SQL query to get outputs from multiple tables

I am using information from multiple tables to try and get the output to be, Supplier ID, Supplier Name, Percent of orders with tracking number.
I need information from many tables, as follows:
Suppliers, this contains supplier ID and supplier name
SupplierSubscriptions, the supplier must have subscriptionid = 91, this contains supplier id.
SalesOrders, this contains each order for every supplier, so it contains supplier id.
Shipments, this contains the salesorder id, with each shipment associated to that order.
Packages, this contains the shipmentid and if the shipment is on the packages table, it contains a tracking number.
What I have so far is:
SELECT DISTINCT so.supplierID, count(*) AS NumberOfOrders FROM SalesOrders so
INNER JOIN suppliers s ON s.SupplierID = so.SupplierID
INNER JOIN SupplierSubscriptions ss ON s.SupplierID = ss.SupplierID
INNER JOIN shipments ship ON ship.SalesOrderID = so.SalesOrderID
INNER JOIN Packages p ON p.ShipmentID = ship.ShipmentID
WHERE ss.SubscriptionID = 91 GROUP BY so.SupplierID
this, obviously, is not what I am after, as it only shows the supplier id and a count of orders...
I'm guessing on parts of the schema, but something like this should work for you:
SELECT so.supplierID,
so.supplierName,
SUM(case when p.trackingNumber is not null then 1 else 0 end) / COUNT(0) as OrdersWithTracking
FROM SalesOrders so
INNER JOIN suppliers s ON s.SupplierID = so.SupplierID
INNER JOIN SupplierSubscriptions ss ON s.SupplierID = ss.SupplierID
INNER JOIN shipments ship ON ship.SalesOrderID = so.SalesOrderID
INNER JOIN Packages p ON p.ShipmentID = ship.ShipmentID
WHERE ss.SubscriptionID = 91
GROUP BY so.SupplierID, so.supplierName

Insert Multiple Tables into one Table

Http://i.stack.imgur.com/z0fSP.png
Http://i.stack.imgur.com/Nd3nB.png
Http://i.stack.imgur.com/5qtRh.png
Http://i.stack.imgur.com/01PVc.png
Http://i.stack.imgur.com/wvibY.png
INSERT INTO OrderArchive
(OrderNumber,OrderDate,StockItem,Quantity,UnitPrice,SalesRep,Customer,ArchiveDate)
SELECT "ORDER".OrderNo,
"ORDER".OrderDate,
Stock.StockNo||' '||Stock.StockDesc,
Orderline.Quantity,
Orderline.UnitPrice,
Person.FirstName||' '||Person.Surname,
Person.FirstName||' '||Person.Surname,
OrderArchive.ArchiveDate
FROM "ORDER"
INNER JOIN Stock
ON Stock.StockNo||' '||Stock.StockDesc = OrderAchive.StockItem
INNER JOIN Orderline
ON Orderline.Quantity = OrderArchive.Quantity
INNER JOIN Orderline
ON Orderline.UnitPrice = OrderArchive.UnitPrice
INNER JOIN Person
ON Person.FirstName||' '||Person.Surname = OrderArchive.SalesRep
INNER JOIN Person
ON Person.FirstName||' '||Person.Surname = OrderArchive.Customer
WHERE "ORDER".OrderDate < DATEADD('M',6,SYSDATE);
I tried to work it out first, but just couldnt manage it .... i am trying to move orders that are older than 6 months to OrderArchive...OrderArchive has OrderNo & Orderdate that come from "ORDER"Table Stock item which is a combination of StockID and Stockdesc from stock table quantity and unit cost are from orderline table salesrep and customer are from person Table and datearchived is a sysdate of the date the order was archived
To do this, you need a way to join the Person record to the TableOrder record. This code assumes you have a PersonID on the TableOrder table. You might have a CustomerID or SalesPersonID or something like that on your TableOrder table to join it to the Person table, but I'm not clear on that.
INSERT INTO ArchiveTable (col_1,col_2,col_3,col_4 etc)
SELECT
o.OrderNo,
o.OrderDate,
p.StockNo||' '||p.StockDesc,
p.FirstName||' '|| p.Surname
FROM TableOrder o
INNER JOIN Person p
ON p.PersonID = o.PersonID
WHERE o.orderdate < DATEADD('M',12,SYSDATE)
I think that you are not getting the expected output from the query, because you are joining the Person table with both SalesRep and Customer names at the same time. Thus, only if an Order has the same name for both SalesRep and Customer, will you get any data. Therefore, I have created different table aliases for the Person table, as below:
INSERT INTO OrderArchive
(OrderNumber,OrderDate,StockItem,Quantity,UnitPrice,SalesRep,Customer,ArchiveDate)
SELECT
"ORDER".OrderNo,
"ORDER".OrderDate,
Stock.StockNo||' '||Stock.StockDesc,
Orderline.Quantity,
Orderline.UnitPrice,
Person_SR.FirstName||' '||Person_SR.Surname,
Person_C.FirstName||' '||Person_C.Surname,
OrderArchive.ArchiveDate
FROM "ORDER"
INNER JOIN Stock
ON Stock.StockNo||' '||Stock.StockDesc = OrderAchive.StockItem
INNER JOIN Orderline
ON Orderline.Quantity = OrderArchive.Quantity
INNER JOIN Orderline
ON Orderline.UnitPrice = OrderArchive.UnitPrice
INNER JOIN Person Person_SR
ON Person_SR.FirstName||' '||Person_SR.Surname = OrderArchive.SalesRep
INNER JOIN Person Person_C
ON Person_C.FirstName||' '||Person_C.Surname = OrderArchive.Customer
WHERE "ORDER".OrderDate < DATEADD('M',6,SYSDATE);
INSERT INTO OrderArchive (OrderNumber,OrderDate,StockItem,Quantity,UnitPrice,SalesRep,Customer)
SELECT "ORDER".OrderNo,
"ORDER".OrderDate,
Stock.StockNo ||' '|| Stock.StockDesc,
Orderline.Quantity,
Stock.UnitCost,
"ORDER".SalesRepID,
Person.FirstName||' '||Person.Surname
FROM Person INNER JOIN
("ORDER" LEFT JOIN
(Orderline INNER JOIN Stock
ON Orderline.StockID=Stock.StockNo)
ON"ORDER".OrderNo=OrderLine.OrderNo)
ON Person.PersonID="ORDER".CustomerID
WHERE "ORDER".OrderDate < ADD_MONTHS (SYSDATE,-6)
ORDER BY "ORDER".OrderNo;
SELECT * FROM OrderArchive;
Nearly Done i just have to get SalesRepID to say firstname surname of salesrep but mostly done :)

Sql query to minus the two tables. What Is wrong?

select table1.t1 from
(
(
select
ItemCategory.Name as Category,
InventoryItems.Name as ItemName,
sum(SalesItems.Quantity) as Quantity,
(InventoryItems.Weight*sum(SalesItems.Quantity)) as Weight,
sum(SalesItems.Amount) as Amount
from SalesInvoices
inner join Sales on Sales.ID = SalesInvoices.SalesID
inner join SalesItems on SalesItems.SalesID = Sales.ID
inner join InventoryItems on InventoryItems.ID = SalesItems.InventoryItemID
inner join ItemCategory on ItemCategory.ID = InventoryItems.ItemCategoryID
inner join BusinessPartners on Sales.BusinessPartnerID = BusinessPartners.ID
where SalesInvoices.Date >= '2013-07-1' and SalesInvoices.Date <= '2013-11-7'
group by ItemCategory.Name,InventoryItems.Name,InventoryItems.Weight
) as t1,
(
select
ItemCategory.Name as Category,
InventoryItems.Name as ItemName,
sum(SalesAdjustmentItems.AdjustedQuantity)*-1 as Quantity,
(sum(SalesAdjustmentItems.AdjustedQuantity)*InventoryItems.Weight)*-1 as
Weight,
sum(SalesAdjustmentItems.AmountReturn)*-1 as Amount
from SalesInvoices
inner join Sales on Sales.ID = SalesInvoices.SalesID
inner join SalesItems on SalesItems.SalesID = Sales.ID
inner join SalesAdjustmentItems on SalesAdjustmentItems.SalesItemID = SalesItems.ID
inner join InventoryItems on InventoryItems.ID = SalesItems.InventoryItemID
inner join ItemCategory on ItemCategory.ID = InventoryItems.ItemCategoryID
inner join SalesAdustment on SalesAdustment.SalesInvoiceID = SalesInvoices.ID
inner join BusinessPartners on Sales.BusinessPartnerID = BusinessPartners.ID
where SalesAdustment.Date>= '2013-07-1' and SalesAdustment.Date <= '2013-11-7'
group by ItemCategory.Name,InventoryItems.Name,InventoryItems.Weight
) as t2
)
as table1
What I am doing wrong in this query. 1st query is for Sales and second query is for Sale returns. I want to get the difference of Sales and Returns. But is giving me error.
Thanks
The SQL minus operator is known as EXCEPT e.g. to find sales that have no invoices:
-- Sales minus SalesInvoices
SELECT ID
FROM Sales
EXCEPT
SELECT SalesID
FROM SalesInvoices;
If you are using older versions,
SELECT ID
FROM Sales
where not exists(SELECT SalesID FROM SalesInvoices where sales.ID=SalesID);