I am having duplicates in end result. I tried using Distinct as well as group by clause.
Select distinct
Orders.OrderNumber, Tracking.TrackingID,
Orders.BalanceDue, Orders.Approved, Orders.Name, Orders.ShipCity ,
Orders.OrderDate, Orders.country, Orders.Shipping, Orders.CartId
from
orders
left join
Tracking on Orders.OrderNumber = Tracking.ordernum
group by
Orders.OrderNumber, Orders.BalanceDue, Tracking.TrackingID,
Orders.Approved, Orders.Name, Orders.ShipCity,
Orders.OrderDate, Orders.country, Orders.Shipping, Orders.CartId
There are 8166 rows in Orders table and I want only that many columns in end result.
![enter image description here][3]
One way to get one tracking id is to use an aggregation function and remove trackingid from the group by clause:
Select o.OrderNumber, max(t.TrackingID) as TrackingId,
o.BalanceDue, o.Approved, o.Name, o.ShipCity,
o.OrderDate, o.country, o.Shipping, o.CartId
from orders l left join
Tracking t
on o.OrderNumber = t.ordernum
group by o.OrderNumber, o.BalanceDue, o.Approved, o.Name, o.ShipCity,
o.OrderDate, o.country, o.Shipping, o.CartId;
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
My problem is that I want to sum the column of quantity with their corresponding employee ID but it doesnt let me rename the result of the query with as
Here is my query:
SELECT Orders.OrderID,Orders.EmployeeID,[Order Details].Quantity
FROM Orders INNER JOIN DimEmployee
ON Orders.EmployeeID=DimEmployee.EmployeeID
INNER JOIN [Order Details]
ON [Order Details].OrderID=Orders.OrderID
It doesnt let me put:
AS name (query)
or (query) AS name
In order for me to use another select query like this:
SELECT SUM([Orders Detail].Quantity) FROM queryResult Group By Orders.EmployeeID
Try this:
SELECT SUM(QUANTITY),EmployeeId FROM(
SELECT ORD.OrderID,ORD.EmployeeID,OD.Quantity
FROM Orders AS ORD
INNER JOIN DimEmployee AS DE
ON ORD.EmployeeID=DE.EmployeeID
INNER JOIN [Order Details] AS OD
ON OD.OrderID = ORD.OrderID
) AS X
Group By EmployeeId
Something like this should give you what you want.
SELECT
Orders.EmployeeID AS EmployeeID,
SUM([Order Details].Quantity) AS TotalQty
FROM Orders
INNER JOIN DimEmployee
ON Orders.EmployeeID=DimEmployee.EmployeeID
INNER JOIN [Order Details]
ON [Order Details].OrderID=Orders.OrderID
GROUP BY
Orders.EmployeeID
You can do this with a straight forward aggregation, or a window function to return all details. You may need to remove the OrderID from the SELECT list and GROUP BY if you don't want the results grouped at that level.
SELECT
Orders.OrderID,
Orders.EmployeeID,
EmpTotal = SUM([Order Details].Quantity)
FROM Orders
INNER JOIN DimEmployee
ON Orders.EmployeeID=DimEmployee.EmployeeID
INNER JOIN [Order Details]
ON [Order Details].OrderID=Orders.OrderID
GROUP BY
Orders.OrderID,
Orders.EmployeeID
SELECT
Orders.OrderID,
Orders.EmployeeID,
PartitionedTotal = SUM([Order Details].Quantity) OVER (PARTITION BY Orders.EmployeeID, Orders.OrderID) --here you may only want to partition by the EmployeeID instead of both
FROM Orders
INNER JOIN DimEmployee
ON Orders.EmployeeID=DimEmployee.EmployeeID
INNER JOIN [Order Details]
ON [Order Details].OrderID=Orders.OrderID
Here is a simple query:
SELECT orders.id, customers.name, COUNT(order_product.id)
FROM orders
INNER JOIN order_product ON orders.id = order_product.order_id
INNER JOIN customers ON orders.customer_id = customers.id
GROUP BY orders.id;
In other words, I want:
The ID of an order.
The number of products (count) in each order.
The customer name of the order.
The problem is about selecting customers.name. I cannot select it directly because it's not in aggregate function nor group by. But there is only one, so I d'ont know why I have to aggregate it. I can do a trick like this to select its name:
SELECT MAX(customers.name)
But I think it's dirty, because I don't want the "max name of a customer for an order" but "the name of the customer for an order". What is the elegant way to do such a thing?
Hope it's clear and not a duplicate.
EDIT: an order have only one customer identified by orders.customer_id. That's why I asking why I have to do such a trick.
Add customers.name to the GROUP BY clause:
SELECT orders.id, customers.name, COUNT(order_product.id)
FROM orders
INNER JOIN order_product ON orders.id = order_product.order_id
INNER JOIN customers ON orders.customer_id = customers.id
GROUP BY orders.id, customers.name
Usually you can simply group by all selected columns that are not arguments to set functions!
Alternatively, you could use window functions
SELECT DISTINCT orders.id, customers.name, COUNT(order_product.id) OVER ( PARTITION BY orders.id)
FROM orders
INNER JOIN products ON orders.id = order_product.order_id
INNER JOIN customers ON orders.customer_id = customers.id;
I am pretty new to using MS SQL 2012 and I am trying to create a query that will:
Report the order id, the order date and the employee id that processed the order
report the maximum shipping cost among the orders processed by the same employee prior to that order
This is the code that I've come up with, but it returns the freight of the particular order date. Whereas I am trying to get the maximum freight from all the orders before the particular order.
select o.employeeid, o.orderid, o.orderdate, t2.maxfreight
from orders o
inner join
(
select employeeid, orderdate, max(freight) as maxfreight
from orders
group by EmployeeID, OrderDate
) t2
on o.EmployeeID = t2.EmployeeID
inner join
(
select employeeid, max(orderdate) as mostRecentOrderDate
from Orders
group by EmployeeID
) t3
on t2.EmployeeID = t3.EmployeeID
where o.freight = t2.maxfreight and t2.orderdate < t3.mostRecentOrderDate
Step one is to read the order:
select o.employeeid, o.orderid, o.orderdate
from orders o
where o.orderid = #ParticularOrder;
That gives you everything you need to go out and get the previous orders from the same employee and join each one to the row you get from above.
select o.employeeid, o.orderid, o.orderdate, o2.freight
from orders o
join orders o2
on o2.employeeid = o.employeeid
and o2.orderdate < o.orderdate
where o.orderid = #ParticularOrder;
Now you have a whole bunch of rows with the first three values the same and the fourth is the freight cost of each previous order. So just group by the first three fields and select the maximum of the previous orders.
select o.employeeid, o.orderid, o.orderdate, max( o2.freight ) as maxfreight
from orders o
join orders o2
on o2.employeeid = o.employeeid
and o2.orderdate < o.orderdate
where o.orderid = #ParticularOrder
group by o.employeeid, o.orderid, o.orderdate;
Done. Build your query in stages and many times it will turn out to be much simpler than you at first thought.
It is unclear why you are using t3. From the question it doesn't sound like the employee's most recent order date is relevant at all, unless I am misunderstanding (which is absolutely possible).
I believe the issue lies in t2. You are grouping by orderdate, which will return the max freight for that date and employeeid, as you describe. You need to calculate a maximum total from all orders that occurred before the date that the order occurred on, for that employee, for every row you are returning.
It probably makes more sense to use a subquery for this.
SELECT o.employeeid, o.orderid, o.orderdate, m.maxfreight
FROM
orders o LEFT OUTER JOIN
(SELECT max(freight) as maxfreight
FROM orders AS f
WHERE f.orderdate <= o.orderdate AND f.employeeid = o.employeeid
) AS m
Hoping this is syntactically correct as I'm not in front of SSMS right now. I also included a left outer join as your previous query with an inner join would have excluded any rows where an employee had no previous orders (i.e. first order ever).
You can do what you want with a correlated subquery or apply. Here is one way:
select o.employeeid, o.orderid, o.orderdate, t2.maxfreight
from orders o outer apply
(select max(freight) as maxfreight
from orders o2
where o2.employeeid = o.employeid and
o2.orderdate < o.orderdate
) t2;
In SQL Server 2012+, you can also do this with a cumulative maximum:
select o.employeeid, o.orderid, o.orderdate,
max(freight) over (partition by employeeid
order by o.orderdate rows between unbounded preceding and 1 preceding
) as maxfreight
from orders o;
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;