SQL order minimum Query - sql

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)

Related

How to create a function that totals an order with several items?

I need to create a function which will return the total of an order. I've been given three tables with the following variables
Table 1 - Order
Order_ID
Date_Placed
Date_Fulfilled
Table 2 - Order Product
Order_ID
Product_ID
Product_Quantity
Table 3 - Product
Product_ID
Price
I'm struggling to put together a coherent function. Any help would be greatly appreciated.
I've already attempted to set up the function with joins between both tables, but am unable to figure out where I should be putting my equation.
BEGIN
SELECT order.order_id, SUM(product.price * order_item.quantity)
FROM `order`
JOIN `order_item` ON order.order_id = order_product.order_id
JOIN `product` ON order_product.product_id = product.product_id;
END $$
You might be surprised, but the orders table is not needed for this query. You can just aggregate off the other two tables:
SELECT oi.order_id, SUM(p.price * oi.quantity)
FROM order_item oi JOIN
product p
ON po.product_id = p.product_id
GROUP BY oi.order_id;
You'll need to take your select statement, and group it by your order.order_id. That way you'll have one row per order, with the sum total of that order.
SELECT order.order_id, SUM(product.price * order_item.quantity) as total_price
FROM `order`
JOIN `order_item` ON order.order_id = order_product.order_id
JOIN `product` ON order_product.product_id = product.product_id
GROUP BY order.order_id
this will work:
SELECT order.order_id, SUM(product.price * order_item.quantity)
FROM order o,
JOIN order_item oi,
JOIN product p where
o.order_id = oi.order_id and
oi.product_id = p.product_id
group by order_product.product_id = product.product_id;

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

SQL sum from single table with join

I have two table orders and orderitems.
order table has id,order_total,recieved_amount
orderitems table has id,order_id,name,total_item
I want the sum of recieved_amount, order_total from the order table and sum of total_item from orderitems. so I used
SELECT SUM(`received_amount`) as totalRecieved,
SUM(`order_total`) as orderTotal
FROM `orders` AS `Order`
LEFT JOIN `order_items` AS `OrderItems`
ON (`OrderItems`.`order_id`=`Order`.`id`)
and
SELECT SUM(`received_amount`) as totalRecieved,
SUM(`order_total`) as orderTotal
FROM `orders` AS `Order`
LEFT JOIN `order_items` AS `OrderItems`
ON (`OrderItems`.`order_id`=`Order`.`id`)
group by order.id
but none of them is giving me the correct result.
You are aggregating at two levels of your data hierarchy. This causes a problem with Cartesian products, for each order.
The solution is to aggregate along order_items before doing the join:
SELECT SUM(received_amount) as totalRecieved,
SUM(order_total) as orderTotal
FROM orders o LEFT JOIN
(SELECT oi.order_id, SUM(total_items) as total_items
FROM order_items oi
GROUP BY oi.order_id
) oi
ON oi.order_id = o.id;
As an alternative, you can benefit from cte structure or a temp table like below:
;with cte (order_id, SumTotalItems) as (
SELECT oi.order_id, SUM(total_items) as SumTotalItems
FROM order_items oi
GROUP BY oi.order_id
)
select sum(o.receivedamount) as SumReceivedAmount
, sum(o.order_total) as SumOrderTotal
, cte.SumTotalItems
from orders o
left outer join cte on o.id = cte.order_id

SQL query based on aggregate and join

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

SQL: list items not sold in between time period

The software we use has two tables for orders, Orders and OrderItems.
I am trying do run a query on the database to show which items have not sold in a period of time.
This is what I have but It's not working ( it brings up all the records)
SELECT
OrderItem.Name,
OrderItem.SKU,
[Order].OrderDate
FROM
[Order]
INNER JOIN OrderItem ON [Order].OrderID = OrderItem.OrderID
WHERE
(OrderItem.SKU NOT IN
(SELECT DISTINCT OrderItem.SKU WHERE ([Order].OrderDate BETWEEN '2014-09-08' AND '2014-01-01')))
You can actually do this with a having clause:
SELECT oi.Name, oi.SKU, max(o.OrderDate) as lastOrderDate
FROM [Order] o INNER JOIN
OrderItem oi
ON o.OrderID = oi.OrderID
GROUP BY oi.Name, oi.SKU
HAVING sum(case when o.OrderDate between '2014-01-01' and '2014-09-08' then 1 else 0 end) = 0;
If you are just looking for orders before this year, it is easier to write the having clause as:
HAVING max(o.OrderDate) < '2014-01-01'
Flip your dates. It should be [Begin Date] Between [End Date]
WHERE (OrderItem.SKU NOT IN
(SELECT DISTINCT OrderItem.SKU
WHERE ([Order].OrderDate BETWEEN '2014-01-01' AND '2014-09-08')))
How about the following:
SELECT oi.Name, oi.SKU, o.OrderDate
FROM [Order] o
INNER JOIN OrderItem oi ON o.OrderID = oi.OrderID
WHERE oi.SKU NOT IN
(
SELECT os.SKU
FROM [Order] os
INNER JOIN OrderItem ois ON os.OrderID = ois.OrderID
WHERE os.OrderDate BETWEEN '2014-01-01' AND '2014-09-08'
)
You have to join to the OrderItem table in the sub query in order to get the SKU.
Looks like your query was build 'upside down'.
SELECT DISTINCT SKU FROM OrderItem oi
WHERE NOT EXISTS
(SELECT 1 FROM Order o
JOIN OrderItem oi2 ON o.OrderID = oi2.OrderID
WHERE oi2.SKU = oi.SKU
AND o.OrderDate BETWEEN '2014-01-01' AND '2014-09-08' );
Ideally, you should have another table containing your distinct items, so you could write the following query to see which items were not sold during a certain period (and may have never been sold at all).
select i.SKU from items
where not exists (
select 1 from OrderItem oi
join Order o on o.OrderID = oi.OrderID
where oi.SKU = i.SKU
and o.OrderDate BETWEEN '2014-01-01' and '2014-09-08'
)
if you don't have such a table, you can select all products that have been ordered at some point, but not during another period
select i.SKU from (
select distinct oi.SKU from OrderItem oi
) i
where not exists (
select 1 from OrderItem oi
join Order o on o.OrderID = oi.OrderID
where oi.SKU = i.SKU
and o.OrderDate BETWEEN '2014-01-01' and '2014-09-08'
)