Joining issue with sql query - sql

We are using shipworks application to manage our orders. With this, we have also developed a small tool which helps in generating different kind of reports based on shipworks data.
So, we are facing little problem with generating reports for sales by Customer. In this report, we are fetching following information:
1. Customer ID, BillFirstName, BillMiddleName, BillLastName, OrderTotal as total from Order table.
2. SalePrice from OrderItem table. Saleprice is the (quantity * unitprice). OrderItem table saves the products with quantity and unit price ordered in a particular order. We have relationship between Order and OrderItem table through OrderID.
3. Discount, Taxes and freight from OrderCharge table. Discount is the sum of all the amounts which have corresponding type column values (COUPON, PROMOTION DISCOUNT, REWARD, CREDIT, PROMOTION, FACEBOOK_FAN_REWARD, VOUCHER) and Taxes is the sum of amount which have corresponding type column values (TAX) and freight is sum of amount which have corresponding type column values (SHIPPING). We have relationship between OrderCharge and Order table through OrderID.
OverAll, we are fetching the above data against each customerID. We also pass some store condition and date condition to get data i.e order belongs to store as we passed and belongs to passed start and end date.
We have made the query for above as:
select derived.CustomerID, derived.BillFirstName, derived.BillMiddleName,
derived.BillLastName, SUM(oi.quantity*oi.UnitPrice) as saleprice, derived.freight,
derived.tax, sum(o.OrderTotal) as total, derived.discount
from (select o.CustomerID, o.BillFirstName, o.BillMiddleName, o.BillLastName
,SUM(oc.amount) as freight, SUM(oc2.amount) as tax, SUM(oc3.amount) as discount
from [Order] o
inner join OrderCharge oc on o.orderID = oc.orderID
and oc.[Type] = 'SHIPPING'
inner join OrderCharge oc2 on o.orderID = oc2.orderID
and oc2.Type = 'TAX'
inner join OrderCharge oc3 on o.orderID = oc3.orderID
and (oc3.Type = 'COUPON'
or oc3.Type = 'PROMOTION DISCOUNT'
or oc3.Type = 'REWARD'
or oc3.Type = 'CREDIT'
or oc3.Type = 'PROMOTION'
or oc3.Type = 'FACEBOOK_FAN_REWARD'
or oc3.Type = 'VOUCHER')
where o.StoreID IN(12005,17005,1005,20005,19005)
and (o.OrderDate between '2013-11-01 00:00:00' and '2013-12-27 23:59:00')
group by o.CustomerID, o.BillFirstName,
o.BillMiddleName, o.BillLastName) as derived
inner join [Order] o on o.CustomerID = derived.CustomerID
inner join orderItem oi on o.orderID = oi.orderID
group by derived.CustomerID, derived.BillFirstName, derived.BillMiddleName,
derived.BillLastName, derived.freight, derived.tax, derived.discount
The above query giving us right data but not summing the discount, freight and taxes. Can any one please suggest me other solution or tell me what is the wrong with the above query?
Waiting for reply

Try this:
SELECT o.CustomerID, o.BillFirstName, o.BillMiddleName, o.BillLastName,
SUM(B.saleprice) AS saleprice, SUM(A.freight) AS freight,
SUM(A.tax) AS tax, SUM(o.OrderTotal) AS total, SUM(A.discount) AS discount
FROM ORDER o
INNER JOIN (SELECT orderID,
SUM(CASE WHEN oc.TYPE = 'SHIPPING' THEN oc.amount ELSE 0 END) AS freight,
SUM(CASE WHEN oc.TYPE = 'TAX' THEN oc.amount ELSE 0 END) AS tax,
SUM(CASE WHEN oc.TYPE IN ('COUPON', 'PROMOTION DISCOUNT', 'REWARD', 'CREDIT', 'PROMOTION', 'FACEBOOK_FAN_REWARD', 'VOUCHER') THEN oc.amount ELSE 0 END) AS discount
FROM OrderCharge oc GROUP BY oc.orderID
) A ON o.orderID = A.orderID
INNER JOIN (SELECT orderID, SUM(oi.quantity * oi.UnitPrice) AS saleprice
FROM OrderItem oi GROUP BY oi.orderID
) B ON o.orderID = B.orderID
WHERE o.StoreID IN(12005,17005,1005,20005,19005) AND
o.OrderDate BETWEEN '2013-11-01 00:00:00' AND '2013-12-27 23:59:00'
GROUP BY o.CustomerID, o.BillFirstName, o.BillMiddleName, o.BillLastName

Related

Retrieve cost on certain date SQL

I have the following tables:
Order (orderID, date, shipID)
Shipping (shipID, price)
PO (prodID, orderID, amount)
Price (prodID, fromDate, price)
I need to retrieve each order ID and the total price including the cost of the items in order + the cost of shipping purchased. The cost of the item has to be the cost of the item on the order date, not the most recent date. The Price table stores the different prices of a product starting at a particular date (fromDate attribute). Hence, the price of a product on day d is the price in the entry with the largest fromDate-value f such that f ≤ d. I understand I can use the command max(fromDate) to retrieve the latest price on an item, however, I cannot figure out how to get the price on a certain date. This is my code so far:
SELECT o.orderId, SUM(pr.price) + SUM(s.price) orderCost
FROM "Order" o
INNER JOIN Shipping s
ON o.shipId = s.shipId
INNER JOIN PO po
ON po.orderId = o.orderId
INNER JOIN Price pr
ON pr.prodId = po.prodId
GROUP BY o.orderId;
Try this
select o.orderId, SUM(pr.price) + SUM(s.price) orderCost
from [Order] o
INNER JOIN Shipping s ON o.shipId = s.shipId
inner join PO po on o.shipId = po.shipId
inner join (select top 1 price from Price pr where fromDate = (select max(fromDate)from Price pr where fromDate <= [date])) pr
on pr.prodID = po.prodID
GROUP BY o.orderId;

Retrieving date an item was ordered on SQL

I have the following tables:
Order (orderID, date, shipID)
Shipping (shipID, price)
PO (prodID, orderID, amount)
Price (prodID, fromDate, price)
I need to retrieve each order ID and the total price including the cost of the items in order + the cost of shipping purchased. The cost of the item has to be the cost of the item on the order date, not the most recent date. The Price table stores the different prices of a product starting at a particular date (fromDate attribute). Hence, the price of a product on day d is the price in the entry with the largest fromDate-value f such that f ≤ d. I understand I can use the command max(fromDate) to retrieve the latest price on an item, however, I cannot figure out how to get the price on a certain date. This is my code so far:
SELECT o.orderId, SUM(pr.price) + SUM(s.price) orderCost
from "Order" o
INNER JOIN Shipping s ON o.shipId = s.shipId
INNER JOIN PO po ON o.orderId = po.orderId
INNER JOIN (SELECT TOP 1 price FROM Price pr WHERE
fromDate = (SELECT MAX(fromDate)FROM Price pr WHERE fromDate <= o."date")) pr
ON pr.prodID = po.prodID
GROUP BY o.orderId;
It gives the following error:
The multi-part identifier "o.date" could not be bound
I am not sure this would quite give me my desired result even if it ran though. Any ideas?
You can first filter the top price on or before your order date using a subquery before joining.
SELECT o.orderId, SUM(pr.price) + SUM(s.price) orderCost
from [Order] o
INNER JOIN Shipping s ON o.shipId = s.shipId
INNER JOIN PO po ON o.orderId = po.orderId
INNER JOIN
(SELECT TOP 1 price, prodID FROM Price pr WHERE
fromDate <= (select max([date]) from [Order])
order by fromDate desc) pr ON pr.prodID = po.prodID
GROUP BY o.orderId;
you rewrite your query like below
SELECT o.orderId, SUM(pr.price+s.price) orderCost
from "Order" o
INNER JOIN Shipping s ON o.shipId = s.shipId
INNER JOIN PO po ON o.orderId = po.orderId
INNER JOIN (SELECT max(fromDate) as fromDate, max(price) as price
,prodID FROM Price pr group by prodID
) pr
ON pr.prodID = po.prodID
where pr.fromDate <= o."date"
GROUP BY o.orderId;
You havn't selected "date" in the first statement that defines "o". Perhaps something like this would work?
with sales as
(
SELECT
o.orderId
, o.date
, SUM(pr.price) + SUM(s.price) orderCost
from "Order" o
INNER JOIN Shipping s ON o.shipId = s.shipId
INNER JOIN PO po ON o.orderId = po.orderId
INNER JOIN (SELECT TOP 1 price FROM Price pr WHERE
fromDate = (SELECT MAX(fromDate)FROM Price pr WHERE fromDate <= o.date)) pr ON pr.prodID = po.prodID
GROUP BY o.orderId, o.date
)
select
orderid
, orderCost
from sales

Left join returning bad values

I'm not very good with SQL queries but I attempted to write this one:
SELECT DATEPART(YY,Orders.OrderDate) as Year,
DATEPART(MM,Orders.OrderDate) as Month,
(SUM(case when OrderDetails.ProductCode = 'XXX' then
OrderDetails.ProductPrice else 0 end) + SUM(Orders.Total))
AS XXX
FROM Orders
LEFT JOIN OrderDetails ON Orders.OrderID = OrderDetails.OrderID
WHERE Orders.OrderStatus = 'Shipped'
GROUP BY DATEPART(MM,Orders.OrderDate), DATEPART(YY,Orders.OrderDate)
ORDER BY DATEPART(YY,Orders.OrderDate),DATEPART(MM,Orders.OrderDate)
The OrderDetails is linked to the Orders table by the field OrderID. In this SELECT query I'm trying to get the SUM of OrderDetails.ProductPrice when the OrderDetails.ProductCode is XXX and add it to the Orders.Total to get total amounts for each month/year.
The query is working except for one problem (that's probably either a amateur mistake or has been worked around several times). When performing the LEFT JOIN, the OrderDetails table can have multiple records linked to the Orders table which is throwing bad results in the SUM(Orders.Total). I've isolated that issue I just can't seem to fix it.
Can anybody point me in the right direction?
If we assume that the XXX product only appears at most once for each order, then this should work:
SELECT year(o.OrderDate) as Year, month(o.OrderDate) as Month,
(COALESCE(SUM(od.ProductPrice), 0) + SUM(o.Total)) AS XXX
FROM Orders o LEFT JOIN
OrderDetails od
ON o.OrderID = od.OrderID AND od.ProductCode = 'XXX'
WHERE o.OrderStatus = 'Shipped'
GROUP BY year(o.OrderDate), month(o.OrderDate)
ORDER BY year(o.OrderDate), month(o.OrderDate);
If it can appear multiple times, then move that part of the aggregation to a subquery:
SELECT year(o.OrderDate) as Year, month(o.OrderDate) as Month,
(COALESCE(XXX, 0) + SUM(o.Total)) AS XXX
FROM Orders o LEFT JOIN
(SELECT od.OrderId, SUM(od.ProductPrice) as XXX
FROM OrderDetails od
WHERE od.ProductCode = 'XXX'
GROUP BY od.OrderId
) od
ON o.OrderID = od.OrderID
WHERE o.OrderStatus = 'Shipped'
GROUP BY year(o.OrderDate), month(o.OrderDate)
ORDER BY year(o.OrderDate), month(o.OrderDate);

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

sum over partition

The following query bring the correct value for totalqty. however it leaves or misses counting the qty for some items, why?
SELECT
PRODID, ITEMDES, QTY, SUM(QTY) over (partition by prodId) as totalqty, StockCode,shipName, shipCompany, shipAddress1, shipAddress2, shipAddress3,shipPostCode,shipcity,shipCountry,shipCounty,customerMessage
FROM orderedItems oi
left join orders o on oi.order_id = o.order_id
WHERE prodId = prodId
AND o.status = 'transaction authorised'
AND o.delTime = '#FORM.delDateselect#'
Group by PRODID,ITEMDES,QTY, StockCode,shipName, shipCompany, shipAddress1, shipAddress2, shipAddress3,shipPostCode,shipcity,shipCountry,shipCounty,customerMessage
ORDER BY PRODID
Your where clause makes the left outer join behave like an inner join. Change it like this:
WHERE
prodId = prodId and
(
o.order_id is null or
(
o.status = 'transaction authorised' AND
o.delTime = '#FORM.delDateselect#'
)
)
The reason is that if there is no matching order in orders o.status will be NULL and thus not equal to 'transaction authorised'.
Furthermore, you don't need the group by. You already have the analytical function that does the SUM for you.