SQL query based on aggregate and join - sql

I am new to SQL and I am trying to join two tables by performing aggregate and join functions. I am using Orderdetails and PurchaseOrderDetails tables to join based on OrderID.
I want to compare the sum on quantity in the OrderDetails table and sum on quantity in the PurchaseOrderDetails table and sum(PurchaseOrderDetails.quantity) != sum(OrderDetails.quantity) based on particular orderID and also join them based on orderID.
I have following two tables:
OrderDetails table design
SELECT TOP 1000 [lineID]
,[orderID]
,[itemNumber]
,[itemDesc]
,[qty]
,[price]
,[priceType]
,[contract]
,[supplierPartID]
,[uom]
,[classDomain]
,[classValue]
,[comments]
,[shipping]
,[tax]
,[reqDeliveryDate]
,[fillInfo]
,[invoiceID]
,[Version]
,[productid]
,[eta]
,[lineOrderID]
FROM [bfdb].[dbo].[OrderDetails]
and PurchaseOrderDetails table design is:
SELECT TOP 1000 [podID]
,[poID]
,[distPN]
,[mfrID]
,[itemNumber]
,[itemName]
,[qty]
,[price]
,[invoiceID]
,[orderID]
,[itemReceived]
,[qtyReceived]
,[distConf]
,[distFillStatus]
,[distLastUpdate]
,[distTracking]
,[distFillDesc]
,[Version]
,[productid]
,[lineOrderID]
FROM [bfdb].[dbo].[PurchaseOrderDetails]
I tried the following query but getting the incorrect result. Suppose if it has 1 row in the OrderDetails table and 2 rows in the PurchaseOrderDetails, then the sum for OrderDetails becomes double after joining. Same with 1 row in PurchaseOrderDetails table if I have more than 1 row in OrderDetails table for that
SELECT
od.orderID, SUM(pod.qty) as Totalqty, SUM(od.qty) as od_qty
FROM
PurchaseOrderDetails pod
INNER JOIN
OrderDetails od ON od.orderID = pod.orderID AND pod.orderID = 15506
GROUP BY
od.orderID
Here is the snapshot of my data

You need to first sum the quantities by orderid for each of these two tables separately and then join. Try this:
select od.orderID, pod.qty as Totalqty, od.qty as od_qty
from (
select orderid, sum(pod.qty) as qty
from PurchaseOrderDetails
group by orderid
) pod
inner join (
select orderid, sum(pod.qty) as qty
from OrderDetails
group by orderid
) od on od.orderid = pod.orderid

You need to simply change the AND condition to a WHERE clause, try this code below:
SELECT od.orderID, SUM(pod.qty) as Totalqty, SUM(od.qty) as od_qty FROM PurchaseOrderDetails pod INNER JOIN OrderDetails od ON od.orderID = pod.orderID WHERE pod.orderID = 15506 GROUP BY od.orderID

Related

SQL order minimum Query

I'm trying to query the products not ordered since 01/01/2017 in SSMS.
So far I've come up with a couple of select count queries but have come up empty trying to figure this out. This has 3 tables attached to the query and I need the product names and IDs attached to the query result.
products table columns:
[product_id], [product_name], [brand_id], [category_id], [model_year], [list_price]
orders table columns:
[order_id], [item_id], [product_id], [quantity], [list_price], [discount]
order_items table columns:
[order_id], [customer_id], [order_status], [order_date], [required_date], [shipped_date],[store_id], [staff_id]
SELECT COUNT (*)
FROM production.products
WHERE NOT EXISTS (SELECT 1
FROM sales.orders
JOIN sales.order_items oi ON orders.order_id = oi.order_id
WHERE orders.order_id = oi.order_id
AND orders.order_date > '2017-01-01');
Break it down into three parts
Order items and orders joined in the date range
Products not in #1
WITH prodcuts_in_date_range as
(
SELECT DISTINCT oi.Product_id
FROM Order_items oi INNER JOIN Orders o on o.Order_id = oi.Order_id
WHERE oi.Order_date > '2017-01-01')
)
SELECT * FROM Products p where p.Product_Id not in (SELECT Product_id from
products_in_date_range)

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);

Left Join and Sum Each Individual Row

I have a table named orders (orderID, customerID, purchaseDate, and paymentType) and orderLine (orderID, upc, productName, quantity, price). I'm trying to join these two tables so that it primarily shows the orders table but then has a total price column for each order on the far right. This is what I have so far but it's adding the total for every single row into one. I want each individual row to have their own sum by multiplying quantity*price based on the orderID.
SELECT orders.orderID, SUM(orderLine.price * orderLine.quantity)
FROM orderLine
LEFT JOIN orders
ON orders.orderID = orderLine.orderID
You need to add group by clause
SELECT orders.orderID, SUM(orderLine.price * orderLine.quantity)
FROM orderLine
LEFT JOIN orders
ON orders.orderID = orderLine.orderID
grou by orders.orderID
SELECT orders.orderID, (SUM(orderLine.price * orderLine.quantity) Over (Order
By orders.orderID))
FROM orderLine
LEFT JOIN orders
ON orders.orderID = orderLine.orderID
Group By orders.orderID
You want all orders, so start with orders. Table aliases also make the query easier to write and to read:
SELECT o.orderID, SUM(ol.price * ol.quantity)
FROM orders o LEFT JOIN
orderLine ol
ON o.orderID = ol.orderID
GROUP BY o.orderID;
Then the answer to your question is GROUP BY.
You would have a very poor data model if you have orderlines that don't have a corresponding order, which is what your version of the query suggests.

SQL Change output of column if duplicate

I have a table which has rows for each product that a customer has purchased. I want to output a column from a SELECT query which shows the time it takes to deliver said item based on whether the customer has other items that need to be delivered. The first item takes 5 mins to deliver and all subsequent items take 2 mins to deliver e.g. 3 items would take 5+2+2=9 mins to deliver.
This is what I have at the moment(Using the Northwind sample database on w3schools to test the query):
SELECT orders.customerid,
orders.orderid,
orderdetails.productid,
CASE((SELECT Count(orders.customerid)
FROM orders
GROUP BY orders.customerid))
WHEN 1 THEN '00:05'
ELSE '00:02'
END AS DeliveryTime
FROM orders
LEFT JOIN orderdetails
ON orderdetails.orderid = orders.orderid
This outputs '00:05' for every item due to the COUNT in my subquery(I think?), any ideas on how to fix this?
Try this
SELECT orders.customerid,
orders.orderid,
orderdetails.productid,
numberorders,
2 * ( numberorders - 1 ) + 5 AS deleveryMinutes
FROM orders
INNER JOIN (SELECT orders.customerid AS countId,
Count(1) AS numberOrders
FROM orders
GROUP BY orders.customerid) t1
ON t1.countid = orders.customerid
LEFT JOIN orderdetails
ON orderdetails.orderid = orders.orderid
ORDER BY customerid
Gregory's answer works a treat and here's my attempts
-- Without each product line item listed
SELECT O.CustomerId,
O.OrderId,
COUNT(*) AS 'NumberOfProductsOrderd',
CASE COUNT(*)
WHEN 1 THEN 5
ELSE (COUNT(*) * 2) + 3
END AS 'MinutesToDeliverAllProducts'
FROM Orders AS O
INNER JOIN OrderDetails AS D ON D.OrderId = O.OrderId
GROUP BY O.CustomerId, O.OrderId
-- Without each product line item listed
SELECT O.CustomerId,
O.OrderId,
D.ProductId,
CASE
WHEN P.ProductsInOrder = 1 THEN 5
ELSE (P.ProductsInOrder * 2) + 3
END AS 'MinutesToDeliverAllProducts'
FROM Orders AS O
INNER JOIN OrderDetails AS D ON D.OrderId = O.OrderId
INNER JOIN (
SELECT OrderId, COUNT(*) AS ProductsInOrder
FROM OrderDetails
GROUP BY OrderId
) AS P ON P.OrderId = O.OrderId
GROUP BY O.CustomerId,
O.OrderId,
D.ProductId,
P.ProductsInOrder
Final code is below for anyone interested:
SELECT O.CustomerId,
O.OrderId,
Group_Concat(D.ProductID) AS ProductID,
CASE COUNT(*)
WHEN 1 THEN 5
ELSE (COUNT(*) * 2) + 3
END AS 'MinutesToDeliverAllProducts'
FROM Orders AS O
INNER JOIN OrderDetails AS D ON D.OrderId = O.OrderId
GROUP BY O.CustomerId

SQl Query :Joining 4 Tables :One to Many

I have 4 Tables in my SQL server DB:
OrderMaster (OrderId [primaryKey], Orderdate, TotalAmount, SupplierName)
OrderDetails (OrderDetailId[primaryKey], OrderId, Item_Id, Quantity, ManufacturerId)
ItemMaster (Item_Id [primaryKey], ITem Name, ITemCost)
ManufacturerMaster (ManuId[primaryKey], ManufacturerName, HandlingFees)
The Relations are:
OrderDetails table Order id is refering the primary key of OrderMAster table(one to many)
OrderDetails table Item_Id is refering the primary key of ItemMaster
ManufacturerIdtable Order id is refering the primary key of ManufacturerMaster
Orderdetails table can have many records for one record in ORderMaster table.
Now I want to have a query to List all Orders which orderdate=05/01/2009 with the below Items as columns values:
Order number
Total Number of Items (number of child records in orderdetail table) for each order
Total (Sum of) ITemcost for all the items in an order.
How to do the Order by?
select OD.Id, count(IM.Item_Id), sum(IM.ItemCost * OD.ItemQuantity)
from OrderMaster OM
join OrderDetail OD on OD.OrderId = OD.OrderId
join ItemMaster IM on IM.Item_Id = OD.Item_Id
group by OD.OrderId
where OD.OrderDate >= '2009/05/01' and OD.OrderDate < '2009/05/02'
updated per new requirements
Something like this
SELECT
OrderMaster.OrderId,
COUNT(OrderDetailId) as TotalUniqeItems,
SUM(Quantity) as TotalItems,
SUM(ItemCost) as CostofUniqueItems,
(
SELECT ItemCost * Quantity
FROM OrderDetail od
JOIN ItemMaster im ON im.Item_Id = od.Item_Id
WHERE od.Order_Id = OrderMaster.OrderId
) as TotalCost
FROM OrderMaster
JOIN OrderDetail ON OrderMaster.OrderId = OrderDetail.OrderId
JOIN ItemMaster ON ItemMaster.Item_Id = OrderDetail.Item_Id
WHERE OrderDate >= '2009/05/01' AND OrderDate <= '2009/05/02'
I included 2 different ways to get Total Numnber of Items and the cost since I was unsure of the exact desired result.
Note, I did not check my syntax, but this should be close.