I'm trying to list the biggest sale of each employee on Northwind database, and so far the best I could do is this;
select top (select count(EmployeeID) from Employees)
max(Quantity*OrderDetails.UnitPrice) TotalSale, FirstName+' '+LastName Name, ProductName from Orders
left join OrderDetails
on
OrderDetails.OrderID=Orders.OrderID
left join Employees
on
Orders.EmployeeID=Employees.EmployeeID
left join Products
on
OrderDetails.ProductID=Products.ProductID
group by FirstName,LastName, ProductName
order by TotalSale desc
But even though I used the group by I get repeated records;
TotalSale Name ProductName
15810,00 Andrew Fuller Côte de Blaye
15810,00 Nancy Davolio Côte de Blaye
10540,00 Robert King Côte de Blaye
10540,00 Anne Dodsworth Côte de Blaye
10540,00 Margaret Peacock Côte de Blaye
9903,20 Janet Leverling Thüringer Rostbratwurst
8432,00 Steven Buchanan Côte de Blaye
7905,00 Janet Leverling Côte de Blaye
7427,40 Andrew Fuller Thüringer Rostbratwurst
Warning: Null value is eliminated by an aggregate or other SET operation.
(9 row(s) affected)
So I have 9 employees and I used top function for that but the employees are not unique, I also tried to use distinct function but it didn't work either.
So I would appreciate a hand please!
Your issue is that you also group by productname. So you will get max sales per employee and per product name.
What you can do is, drop the product name in group by, in this case you will see max total sales only per employee.
select max(Quantity*OrderDetails.UnitPrice) TotalSale, FirstName+' '+LastName Name
from Orders
left join [Order Details] as OrderDetails on OrderDetails.OrderID=Orders.OrderID
left join Employees on Orders.EmployeeID=Employees.EmployeeID
left join Products on OrderDetails.ProductID=Products.ProductID
group by FirstName,LastName
order by TotalSale desc
In case you want to see the product name as well, you can encapsulate your query in a subquery and create a rownum based on employee name and order by total sales. You can select rows with rownum 1 in the outer query. Use rank function in case you need to show all occurances of product names.
SELECT TotalSale, Name, ProductName
FROM
(
select max(Quantity*OrderDetails.UnitPrice) TotalSale
,FirstName + ' ' + LastName Name
,ProductName
,Rnk = Rank() OVER(PARTITION BY Employees.EmployeeId ORDER BY MAX(Quantity*OrderDetails.UnitPrice) DESC)
from Orders
left join [Order Details] as OrderDetails on OrderDetails.OrderID=Orders.OrderID
left join Employees on Orders.EmployeeID=Employees.EmployeeID
left join Products on OrderDetails.ProductID=Products.ProductID
group by FirstName,LastName, Employees.EmployeeId, ProductName
) as sub
where sub.Rnk = 1
order by Name
Related
SELECT a.FirstName, a.LastName, Count(cai.ArtistID)
FROM Artist a
JOIN CUSTOMER_ARTIST_INT cai ON(a.ArtistID=cai.ArtistID)
GROUP BY a.FirstName, a.LastName
Gives me an output of
FirstName LastName COUNT(CAI.ArtistID)
Luke Skywalker 2
Han Solo 7
Darth Vader 3
However, my query must only give me the one with the highest Count thus the output should be:
FirstName LastName COUNT(CAI.ArtistID)
Han Solo 7
I know I have to put the MAX function but i have no idea how.
you can use top 1 order by desc as below
SELECT top (1) a.FirstName, a.LastName, Count(cai.ArtistID)
FROM Artist a
JOIN CUSTOMER_ARTIST_INT cai ON (a.ArtistID=cai.ArtistID)
GROUP BY a.FirstName, a.LastName
order by count(cai.Artistid) desc
If you are looking for certain category you might require to use row_number
I am creating some queries for my project, but I face some difficulties with the follow ones:
A SELECT statement containing a subquery to retrieve a list of Locations (location id and street_address) that have employees with higher salary than the average of their department. The list must contain the number of those employees and their total salary per location. Name these aggregates respectively "emp" and "totalsalary". The locations in the list must be ordered by location_id.
Select LOCATION_ID, STREET_ADDRESS
from HR.LOCATIONS IN
(Select Employee_id
from HR.Employees
Where Salary > round(avg(SALARY)))
order by location_id;
error: SQL command not properly ended
and the second query is the following
The JOB_HISTORY table can contain more than one entries for an employee who was hired more than once. Create a query to retrieve a list of Employees that were hired more than once. Include the columns EMPLOYEE_ID, LAST_NAME, FIRST_NAME and the aggregate "Times Hired".
SELECT FIRST_NAME,LAST_NAME,EMPLOYEE_ID,
count (*)as TIMES_HIRED
from HR.JOB_HISTORY, HR.EMPLOYEES
where EMPLOYEE_ID= LAST_NAME
having COUNT(*) >1;
error: not a single-group
Try these hope they help. I am making an assumption that employee table has Location_Id column. I am adding Employee_id to Group by to make sure you get correct TotalSalary:
Select LOCATION_ID, STREET_ADDRESS, Count(Employee_id) AS emp, SUM(salary) AS totalsalary
from HR.LOCATIONS INNER JOIN
(Select Employee_id, salary
from HR.Employees
Having Salary > round(avg(SALARY), 0)) AS Emp ON HR.LOCATION_ID = Emp.Location_ID
Group By LOCATION_ID, STREET_ADDRESS, Employee_id
order by location_id;
For the second question:
SELECT FIRST_NAME,LAST_NAME,EMPLOYEE_ID,
count(Employee_id) as TIMES_HIRED
from HR.JOB_HISTORY inner join HR.EMPLOYEES On JOB_HISTORY.Employee_id = Employees.Employee_id
Group By FIRST_NAME,LAST_NAME,EMPLOYEE_ID
Having count(Employee_id) >1;
I have a table Called DEPARTMENTS with Columns:
DepartmentID
DepartmentName
Another table Called EMPLOYEE with Columns:
EmployeeID
DepartmentID
EmployeeName
Salary
I need a JOIN query with possibly Group By to display DepartmentName and AVERAGE Salary
Basically the Output should display:
DepartmentX 40000
DepartmentY 15000
DepartmmentZ 35000
You need to use AVG() aggregate function with JOIN between two tables like
SELECT d.DepartmentName,
AVG(e.Salary) as average_salary
FROM Employee e
JOIN DEPARTMENTS d ON e.DepartmentID = d.DepartmentID
GROUP BY e.DepartmentID;
(OR) get the average first and then perform a JOIN like
SELECT d.DepartmentName,
xx.average_salary
FROM DEPARTMENTS d
JOIN (
select DepartmentID, AVG(Salary) as average_salary
from Employee
GROUP BY DepartmentID) xx ON xx.DepartmentID = d.DepartmentID;
I have two queries:
SELECT city, count(id) as num_of_applicants
FROM(
select distinct(students.id), city
FROM STUDENTS INNER JOIN APPLICATIONS ON STUDENTS.ID = APPLICATIONS.STUDENT_ID
WHERE APPLICATIONS.COLLEGE_ID = '28'
) AS derivedTable
GROUP BY city;
SELECT city, count(id) as num_of_accepted_applicants
FROM
(select applications.id, city FROM
STUDENTS INNER JOIN APPLICATIONS ON STUDENTS.ID = APPLICATIONS.STUDENT_ID
WHERE status = 'Accepted' and college_id = '28') as tbl
GROUP BY city
one give the number of applicants for each college and one give the number of accepted applicants in each college, but I want to get a result in on query (instead of) where the result is something like:
city | number_of_applicants | number_of_accepted_applicants
You can simplify (fyi: I didn't understand why you used the derived tables, you could have just put the COUNT and GROUP BY on the inner queries) and combine the queries as this:
SELECT city
, COUNT(*) AS num_of_applicants
, SUM( CASE
WHEN status = 'Accepted' THEN 1
ELSE 0
END
) AS num_of_accepted_applicants
FROM STUDENTS
JOIN APPLICATIONS
ON STUDENTS.ID = APPLICATIONS.STUDENT_ID
WHERE college_id='28'
GROUP BY city;
Another way is to continue with the technique of derived tables. Make each of your queries a derived table and JOIN on the city - but that would not perform as well.
I've been trying for hours but can't get the query to do what I want using DB2.
From table Company and Users I have the following tickets quantity info per company/user
user company quantity
------------ ------------ ------------
mark nissan 300
tom toyota 50
steve krysler 80
mark ford 20
tom toyota 120
jose toyota 230
tom nissan 145
steve toyota 10
jose krysler 35
steve ford 100
This is generated by the query:
SELECT T.USER, COUNT(T.USER) AS QUANTITY, T.COMPANY FROM TICKET T
INNER JOIN COMPANY P ON P.COMPANY = T.COMPANY
GROUP BY (T.USER, T.COMPANY) -- ORDER BY QUANTITY DESC
What I want to see is the top user for each company, so given the data above, the query should show me:
user company quantity (Top user per company)
------------ ------------ --------------------------------
mark nissan 300
jose toyota 230
steve ford 100
steve krysler 80
How can I write the SQL to return this result?
Final answer (noted in a comment):
SELECT user, quantity, company
FROM (SELECT user, quantity, company,
RANK () OVER (PARTITION BY company ORDER BY quantity DESC) AS r
FROM (SELECT T.USER, COUNT(T.USER) AS QUANTITY, T.COMPANY
FROM TICKET T JOIN COMPANY P ON P.COMPANY = T.COMPANY
GROUP BY (T.USER, T.COMPANY) ) s ) t
WHERE r = 1;
Build it up step by step.
Find the maximum quantity for each company, assuming the first data table shown in the question is called 'Tickets':
SELECT Company, MAX(Quantity) AS MaxQuantity
FROM Tickets
GROUP BY Company;
Now, find the data for the user(s) with that maximum quantity for that company:
SELECT T.User, T.Company, M.MaxQuantity
FROM Tickets AS T
JOIN (SELECT Company, MAX(Quantity) AS MaxQuantity
FROM Tickets
GROUP BY Company) AS M
ON T.Company = M.Company AND T.Quantity = M.MaxQuantity;
If the top quantity for a particular company was, say, 200 and two users both scored 200 for that company, then this query lists both users.
Now, if you mean that the query you show in the question generates the first result table, then what I called tickets just above needs to be the derived table:
SELECT T.User, COUNT(T.User) AS Quantity, T.Ccompany
FROM Ticket AS T
INNER JOIN Company AS P ON P.Company = T.Company
GROUP BY (T.User, T.Company)
ORDER BY QUANTITY DESC
In which case, we can use a WITH clause (syntax unchecked, but I think it is correct per SQL standard):
WITH Tickets AS
(SELECT T.User, COUNT(T.User) AS Quantity, T.Ccompany
FROM Ticket AS T
JOIN Company AS P ON P.Company = T.Company
GROUP BY (T.User, T.Company)
)
SELECT T.User, T.Company, M.MaxQuantity
FROM Tickets AS T
JOIN (SELECT Company, MAX(Quantity) AS MaxQuantity
FROM Tickets
GROUP BY Company) AS M
ON T.Company = M.Company AND T.Quantity = M.MaxQuantity;
Clearly, you can also write the WITH sub-query out twice if you prefer.
This should work. Create a derived view to calculate the Quantity per user and per company. Then get the max of then Quantity and then join the max back to the the calculation of the quantity.
SELECT p.company,
t.user,
t.quantity
FROM (SELECT MAX(t.quantity) max_quantity,
t.company
FROM (SELECT
COUNT(t.user) quantity,
t.company
FROM ticket t
GROUP BY t.company) t) maxq
INNER JOIN (SELECT t.user,
t.company,
COUNT(t.user) quantity
FROM ticket t
GROUP BY t.company,
t.user) t
ON maxq.max_quantity = t.quantity
AND maxq.company = t.company
INNER JOIN company p
ON p.company = t.company
ORDER BY t.quantity DESC
A working sample that shows the top users by tag for the StackOverflow data can be found here.