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.
Related
I want to view the top 300 items ordered by total net price, how do I do this please?
Using SSMS 2014
If I remove group by I get error: Column 'orderitems.orderid' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Please see workings below:
select top 300
orderitems.orderid, orders.traderid, orders.orderdate,
SUM(orderitems.nettprice) AS nettprice
from orderitems
INNER JOIN orders ON orders.tradertype = 'S' AND orders.id =
orderitems.orderid
where orderitems.ordertype = 'PO'
group by orderitems.orderid, orders.traderid, orders.orderdate,
orderitems.nettprice
order by orderitems.nettprice DESC
You need to order by the SUM value. You can either put that in the ORDER BY explicitly, or you can use the SELECT column name without a table reference (in other words the column alias you use in the SELECT)
I strongly recommend you use short table aliases to make your code more readable
select top 300
oi.orderid,
o.traderid,
o.orderdate,
SUM(oi.nettprice) AS nettprice
from orderitems AS oi
INNER JOIN orders AS o ON o.tradertype = 'S' AND o.id = oi.orderid
where oi.ordertype = 'PO'
group by
oi.orderid, o.traderid, o.orderdate
order by
nettprice DESC
-- alternatively
order by
SUM(oi.nettprice) DESC
Perhaps what you need here is a windowed SUM and then a TOP. The PARTITION BY clause is based on this comment:
SELECT TOP (300)
oi.orderid,
o.traderid,
o.orderdate,
SUM(oi.nettprice) OVER (PARTITION BY oi.itemnumber, oi.partid, oi.quantity) AS totalnettprice
FROM dbo.orderitems oi
INNER JOIN dbo.orders o ON o.id = oi.orderid
WHERE o.tradertype = 'S'
AND oi.ordertype = 'PO'
ORDER BY oi.totalnettprice DESC;
Very simple:
select top 300
itm.orderid,
ord.traderid,
ord.orderdate,
SUM(itm.nettprice) AS price
from orderitems itm
INNER JOIN orders ord ON
ord.tradertype = 'S' AND ord.id = itm.orderid
where itm.ordertype = 'PO'
group by
itm.orderid,
ord.traderid,
ord.orderdate
order by price DESC
How do I add more columns without changing the result?
Currently this script gets the top 300 purchase order results by order value using a sum & grouping by the order items oi.nettprice This shows the correct results as shown below.
Results shown here
select top 300
oi.orderid, o.traderid, o.orderdate,
SUM(oi.nettprice) AS nettprice
from orderitems AS oi
INNER JOIN orders AS o ON o.tradertype = 'S' AND o.id = oi.orderid
where oi.ordertype = 'PO'
AND oi.status != 'CANCELLED'
group by
oi.orderid, o.traderid, o.orderdate
order by
nettprice DESC
Adding any additional columns to show more information changes the results and alters the sum of oi.nettprice as shown below, I've tried to use group by rollup but this gives the value in a separate row with the other column values as NULL.
select top 300
oi.orderid, o.traderid,
o.orderdate, oi.partid, oi.description, oi.partrevisionid,
SUM(oi.nettprice) AS nettprice
from orderitems AS oi
INNER JOIN orders AS o ON o.tradertype = 'S' AND o.id = oi.orderid
group by rollup
(oi.orderid, o.traderid, o.orderdate, oi.ordertype, oi.status, oi.partid, oi.description,
oi.partrevisionid)
HAVING oi.ordertype ='PO'
AND oi.status != 'CANCELLED'
order by
nettprice DESC
Results using Group by rollup
How can I clear this up to include columns from either table with the correct total (SUM) for each purchase order without affecting the results?
Use sum() partition by to get the desired result
SELECT top 300 oi.orderid,
o.traderid,
o.orderdate,
oi.partid,
oi.description,
oi.partrevisionid,
SUM(oi.nettprice) OVER(PARTITION BY oi.orderid, o.traderid, o.orderdate) AS nettprice
FROM orderitems AS oi
INNER JOIN orders AS o ON o.tradertype = 'S'
AND o.id = oi.orderid
WHERE oi.ordertype = 'PO'
AND oi.status != 'CANCELLED'
ORDER BY nettprice DESC
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
I have this query in a view that I cannot index because of the referenced table t. I've converted to a sub-query which doesn't work either and is a smidgen slower anyway.
I simply need the last price a productid was sold for.
SELECT op.productId, op.Price, o.createdat
from (
SELECT max(op.OrderProductid), MAX(o.OrderId)
FROM dbo.OrderProduct op
INNER JOIN dbo.Order so ON op.OrderId = so.OrderId
WHERE o.StatusId IN (1,2,3)
GROUP BY op.ProductId
) t
join OrderProduct op on op.Productid = t.Productid
join Order o ON o.OrderId = op.OrderId
Considering your last statement:
I simply need the last price a productid was sold for.
You can use row_number for this:
select *
from (
select op.productid, op.price, o.createdat,
row_number() over (partition by op.productid order by o.orderid desc) rn
from orderproduct op
join order o on op.orderid = o.orderid
) t
where rn = 1
I have two tables
Order with columns:
OrderID,OrderDate,CID,EmployeeID
And OrderItem with columns:
OrderID,ItemID,Quantity,SalePrice
I need to return the CustomerID(CID), number of orders per customer, and each customers total amount for all orders.
So far I have two separate queries. One gives me the count of customer orders....
SELECT CID, Count(Order.OrderID) AS TotalOrders
FROM [Order]
Where CID = CID
GROUP BY CID
Order BY Count(Order.OrderID) DESC;
And the other gives me the total sales. I'm having trouble combining them...
SELECT CID, Sum(OrderItem.Quantity*OrderItem.SalePrice) AS TotalDollarAmount
FROM OrderItem, [Order]
WHERE OrderItem.OrderID = [Order].OrderID
GROUP BY CID
I'm doing this in Access 2010.
You would use COUNT(DISTINCT ...) in other SQL engines:
SELECT CID,
Count(DISTINCT O.OrderID) AS TotalOrders,
Sum(OI.Quantity*OI.SalePrice) AS TotalDollarAmount
FROM [Order] O
INNER JOIN [OrderItem] OI
ON O.OrderID = OI.OrderID
GROUP BY CID
Order BY Count(DISTINCT O.OrderID) DESC
Which Access unfortunately does not support. Instead you can first get the Order dollar amounts and then join them before figuring the order counts:
SELECT CID,
COUNT(Orders.OrderID) AS TotalOrders,
SUM(OrderAmounts.DollarAmount) AS TotalDollarAmount
FROM [Orders]
INNER JOIN (SELECT OrderID, Sum(Quantity*SalePrice) AS DollarAmount
FROM OrderItems GROUP BY OrderID) AS OrderAmounts
ON Orders.OrderID = OrderAmounts.OrderID
GROUP BY CID
ORDER BY Count(Orders.OrderID) DESC
If you need to include Customers that have orders with no items (unusual but possible), change INNER JOIN to LEFT OUTER JOIN.
Create a query which uses your 2 existing queries as subqueriers, and join the 2 subqueries on CID. Define your ORDER BY in the parent query instead of in a subquery.
SELECT
sub1.CID,
sub1.TotalOrders,
sub2.TotalDollarAmount
FROM
(
SELECT
CID,
Count(Order.OrderID) AS TotalOrders
FROM [Order]
GROUP BY CID
) AS sub1
INNER JOIN
(
SELECT
CID,
Sum(OrderItem.Quantity*OrderItem.SalePrice)
AS TotalDollarAmount
FROM OrderItem INNER JOIN [Order]
ON OrderItem.OrderID = [Order].OrderID
GROUP BY CID
) AS sub2
ON sub1.CID = sub2.CID
ORDER BY sub1.TotalOrders DESC;