SQL Distinct Sum - sql

SELECT DISTINCT
E.FirstName + ' ' + E.LastName [Full Name],
P.ProductName,
OD.Quantity
FROM Employees E,
Products P,
[Order Details] OD,
Orders O
WHERE
E.EmployeeID = O.EmployeeID
AND O.OrderID = OD.OrderID
AND OD.ProductID = P.ProductID
In the Northwind gives back duplicate FullNames and ProductNames because of the Quantity which is changed (because of the date shipped each time).
I want to present only a Name to a specific ProductName with the Total Quantity and not divided.

You need to use GROUP BY with SUM:
SELECT
e.FirstName + ' ' + e.LastName AS [Full Name],
p.ProductName,
SUM(od.Quantity) AS [Quantity]
FROM Employees e
INNER JOIN Orders o
ON o.EmployeeID = e.EmployeeID
INNER JOIN [Order Details] od
ON od.OrderID = o.OrderID
INNER JOIN Products p
ON p.ProductID = od.ProductID
GROUP BY
e.FirstName + ' ' + e.LastName,
p.ProductName
Note, you need to stop using the old-style JOIN syntax.

I think,it was a good question for discussion.
Correct query always depend upon your actual requirement.
I think your table is too much normalise.In such situation most of them will also keep Employeeid in order_detail table.
At the same time,most of them keep sum value in Order table.
Like sum of quantity,sum of amount etc per orderid in order table.
you can also create view without aggregate function joining all the table.
IMHO,Using Group By clause on so many column and that too on varchar column is bad idea.
Try something like this,
;With CTE as
(
SELECT
E.FirstName + ' ' + E.LastName [Full Name],
O.OrderID,od.qty,P.ProductName
FROM Employees E
inner join Orders O on E.EmployeeID = O.EmployeeID
inner join [Order Details] OD on o.orderid=od.orderid
inner join [Products] P on p.ProductID=od.ProductID
)
,CTE1 as
(
select od.orderid, sum(qty) TotalQty
from CTE c
group by c.orderid
)
select c.[Full Name],c1.TotalQty, P.ProductName from cte c
inner join cte1 c1 on c.orderid=c1.orderid

Related

FORMAT(SUM(Value*Value), 'C') does not allow me to order by DESC properly

I'm currently trying to list OrderRevenue descending, but it lists the values descending improperly when I test my query.
What I've tried using:
SELECT o.OrderID, DATEPART(YEAR,o.OrderDate) AS OrderYear, DATEPART(QUARTER,o.OrderDate) AS OrderQuarter,
E.FirstName + ' ' + E.LastName AS EmployeeName, C.CustomerName, S.ShipperName, SUM(d.Quantity) AS OrderItems, FORMAT(SUM(d.Quantity*p.Price), 'C') AS OrderRevenue
FROM Orders o
INNER JOIN Employees e
ON o.EmployeeID = e.EmployeeID
INNER JOIN Customers c
ON o.CustomerID = c.CustomerID
INNER JOIN Shippers s
ON o.ShipperID = s.ShipperID
INNER JOIN OrderDetails d
ON o.OrderID = d.OrderID
INNER JOIN Products p
ON d.ProductID = p.ProductID
GROUP BY o.OrderID, DATEPART(YEAR,o.OrderDate), DATEPART(QUARTER,o.OrderDate),
E.FirstName + ' ' + E.LastName, C.CustomerName, S.ShipperName, P.Price
ORDER BY OrderRevenue DESC
What it prints out for me:
OrderRevenue
$997.50
$997.50
$986.50
$98.00
$977.20
As you can see it is not properly descending in value. Did I use the Format() method incorrectly?
The SQL Schema I'm using is public, so feel free to test your query results on W3 if that would help you, help me better:
https://www.w3schools.com/sql/trysqlserver.asp?filename=trysql_func_sqlserver_datepart
Would really appreciate any explanation as to why SQL Server doesn't like my code. Thanks!
You can add this ORDER BY SUM(d.Quantity*p.Price) DESC in order by
SELECT o.OrderID, DATEPART(YEAR,o.OrderDate) AS OrderYear, DATEPART(QUARTER,o.OrderDate) AS OrderQuarter,
E.FirstName + ' ' + E.LastName AS EmployeeName, C.CustomerName, S.ShipperName, SUM(d.Quantity) AS OrderItems, FORMAT(SUM(d.Quantity*p.Price), 'C') AS OrderRevenue
FROM Orders o
INNER JOIN Employees e
ON o.EmployeeID = e.EmployeeID
INNER JOIN Customers c
ON o.CustomerID = c.CustomerID
INNER JOIN Shippers s
ON o.ShipperID = s.ShipperID
INNER JOIN OrderDetails d
ON o.OrderID = d.OrderID
INNER JOIN Products p
ON d.ProductID = p.ProductID
GROUP BY o.OrderID, DATEPART(YEAR,o.OrderDate), DATEPART(QUARTER,o.OrderDate),
E.FirstName + ' ' + E.LastName, C.CustomerName, S.ShipperName, P.Price
ORDER BY SUM(d.Quantity*p.Price) DESC
Or you can do it like this also
select *,FORMAT(f1.OrderRevenue, 'C') as OrderRevenue from (SELECT o.OrderID, DATEPART(YEAR,o.OrderDate) AS OrderYear, DATEPART(QUARTER,o.OrderDate) AS OrderQuarter,
E.FirstName + ' ' + E.LastName AS EmployeeName, C.CustomerName, S.ShipperName, SUM(d.Quantity) AS OrderItems, SUM(d.Quantity*p.Price) AS OrderRevenue
FROM Orders o
INNER JOIN Employees e
ON o.EmployeeID = e.EmployeeID
INNER JOIN Customers c
ON o.CustomerID = c.CustomerID
INNER JOIN Shippers s
ON o.ShipperID = s.ShipperID
INNER JOIN OrderDetails d
ON o.OrderID = d.OrderID
INNER JOIN Products p
ON d.ProductID = p.ProductID
GROUP BY o.OrderID, DATEPART(YEAR,o.OrderDate), DATEPART(QUARTER,o.OrderDate),
E.FirstName + ' ' + E.LastName, C.CustomerName, S.ShipperName, P.Price) f1
ORDER BY f1.OrderRevenue DESC

SQL Subqueries - Exists – Any - All

I have a problem facing this subquery SQL exercice,using Northwind DB:
**16.
From order number 10251 show employee's name,company's name, order's
date,name of each product,quantity,unit price and
final price (= unitprice * quantity – unitprice*quantity*discount)
**
The following is my attempt of a solution, each of the subqueries work fine by their own,giving the expected result but it fails when combined together in the same query
select
(select FirstName from Employees where EmployeeID=Orders.EmployeeID)as 'Name',
(select Customers.CompanyName from Customers where Customers.CustomerID = Orders.CustomerID)'Company name' ,
(select Products.ProductName,Products.UnitPrice,
[Order Details].Quantity,
(Products.UnitPrice*[Order Details].Quantity-Products.UnitPrice*[Order Details].Quantity*[Order Details].Discount)
AS 'Final Price' from Products
INNER JOIN [Order Details] on Products.ProductID= [Order Details].ProductID
WHERE [Order Details].OrderID=10251),
Orders.OrderDate
from Orders
where OrderID=10251
I believe your query was failing because the third subquery (for Final Price) was returning a relation, as opposed to a scalar value.
I've re-written the query in a form that opts for joins rather than subqueries. Subqueries can be useful but I think using joins here makes the query little easier to read and work with.
select firstName as Name,
C.companyName as CompanyName,
P.UnitPrice * OD.Quantity
- (P.UnitPrice * OD.Quantity * OD.Discount)
as FinalPrice
from Orders as O
left join Employees as E
on E.employeeId = O.employeeId
left join Customers as C
on C.customerId = O.customerId
left join [Order Details] as OD
on OD.orderId = O.orderId
left join Products as P
on P.productId = OD.produtId

How can I use the return of a select into another select in order to sum them?

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

Insufficient output from SQL query

I'm using the northwind db: http://dev.assets.neo4j.com.s3.amazonaws.com/wp-content/uploads/Northwind_diagram.jpg
I have to output all orders placed by CustomerID ALFKI with more than one unique product. I get the correct orders out, but I can't figure out why it's only printing one product name per order.
My query:
SELECT a.OrderID, p.ProductName
FROM Products p
INNER JOIN 'Order Details' a
ON (p.ProductID = a.ProductID)
INNER JOIN Orders b
ON (a.OrderID = b.OrderID)
WHERE (b.CustomerID = 'ALFKI')
GROUP BY a.OrderID
HAVING COUNT(DISTINCT a.ProductID) > 1
You need the GROUP BY and HAVING to be part of a subquery, with your primary query selecting the detail using the list of OrderIDs returned from the subquery as filter criteria. Try the following syntax for T-SQL:
SELECT
a.OrderID,
p.ProductName
FROM
Products p
INNER JOIN [Order Details] a
ON (p.ProductID = a.ProductID)
INNER JOIN Orders b
ON (a.OrderID = b.OrderID)
WHERE
a.OrderID IN
(
SELECT a.OrderID
FROM [Order Details] a
INNER JOIN Orders b
ON (a.OrderID = b.OrderID)
WHERE (b.CustomerID = 'ALFKI')
GROUP BY a.OrderID
HAVING COUNT(DISTINCT a.ProductID) > 1
)

Northwind: Select EmployeeID where the employee's average amount of sales exceeds the average amount of orders

I am trying to select EmployeeID,FirstName where the average amount of sales of emplyee exceeds the average amount of orders. I calculate the average amount of orders and average amount of sales of each employee but I could not perform the comparision because of subquery returns more than one value.
Average amount of orders:
select SUM((od.UnitPrice*od.Quantity)*(1-Discount))/COUNT(distinct o.OrderID)
from [Order Details] od
join Orders o on o.OrderID=od.OrderID join Employees e on e.EmployeeID= o.EmployeeID
and
this is the amount of average sales for each employee:
select e.FirstName, SUM((od.UnitPrice*od.Quantity)*(1-Discount))/COUNT(distinct o.OrderID) as AmountOfAverageOfSales
from [Order Details] od join Orders o on o.OrderID=od.OrderID join Employees e on e.EmployeeID= o.EmployeeID
group by e.FirstName
I want to reach the EmployeeID,FirstName where amount of average sales of an employee exceeds the average amount of orders but as I said before subquery (second query) returns more then one value so query is not working when I use where. How can I write this query?
I am sorry If I waste time of someone. I have just solved it by using having.
select e.FirstName
from (Orders o inner join Employees e on e.EmployeeID = o.EmployeeID inner join [Order Details] od on o.OrderID=od.OrderID) group by e.FirstName
having SUM((od.UnitPrice*od.Quantity)*(1-od.Discount))/COUNT(distinct o.OrderID) > (select SUM((od.UnitPrice*od.Quantity)*(1-od.Discount))/COUNT(distinct o.OrderID)
from [Order Details] od join Orders o on od.OrderID = o.OrderID)
Not sure if you're needing the AvgOrders per employee or AvgOrders throughout. If it's the former...
select e.*, AvgOrders.AverageOrders, AvgSales.AmountOfAverageOfSales
From Employees e
inner join (select e.EmployeeID, SUM((od.UnitPrice*od.Quantity)*(1-Discount))/COUNT(distinct o.OrderID) as AverageOrders
from [Order Details] od
join Orders o on o.OrderID=od.OrderID
join Employees e on e.EmployeeID= o.EmployeeID
group by e.EmployeeID)) AvgOrders on (e.EmployeeId = AvgOrders.EmployeeId)
inner join (select e.EmployeeID, SUM((od.UnitPrice*od.Quantity)*(1-Discount))/COUNT(distinct o.OrderID) as AmountOfAverageOfSales
from [Order Details] od
join Orders o on o.OrderID=od.OrderID
join Employees e on e.EmployeeID= o.EmployeeID
group by e.EmployeeID) AvgSales on (e.EmployeeId = AvgSales.EmployeeId)
WHERE AvgSales.AmountOfAverageOfSales > AvgOrders.AverageOrders
If it's the latter you could use...
select e.*, AvgOrders.AverageOrders, AvgSales.AmountOfAverageOfSales
From Employees e
inner join (select SUM((od.UnitPrice*od.Quantity)*(1-Discount))/COUNT(distinct o.OrderID) as AverageOrders
from [Order Details] od
join Orders o on o.OrderID=od.OrderID)) AvgOrders on (1=1)
inner join (select e.EmployeeID, SUM((od.UnitPrice*od.Quantity)*(1-Discount))/COUNT(distinct o.OrderID) as AmountOfAverageOfSales
from [Order Details] od
join Orders o on o.OrderID=od.OrderID
join Employees e on e.EmployeeID= o.EmployeeID
group by e.EmployeeID) AvgSales on (e.EmployeeId = AvgSales.EmployeeId)
WHERE AvgSales.AmountOfAverageOfSales > AvgOrders.AverageOrders