SQL to find the maximum number in a grouped column result - sql

I want to display only the highest "TotalSales" after grouping by empname column.
Please below is my SQL statement.
select e.empname as "EmployeeName", sum(p.price) as "TotalSales"
from employees e
join orders o on e.employee_id = o.empid
join products p on o.orderID = p.orderID
group by e.empname
order by TotalSales desc

Related

JOINS AND SUBQUERY

Question -
Display customer Id, name, and total number of orders, for orders handled by salesman Marshall, but only if customer name begins on General or ends on Electric. Exclude customers who placed a single order, but include customers without orders as well. Sort the result based on the total number of orders descending and then by name ascending.
Do not use LIKE operator and do not join 3 tables.
Questions output
Current Query
SELECT c.customer_id,
c.name,
Count(o.order_id) "# of Orders"
FROM customers c
left join orders o
ON c.customer_id = o.customer_id
WHERE Substr(c.name, 1, 7) = 'General'
OR Substr(c.name, -8) = 'Electric'
AND o.order_id IN (SELECT o.order_id
FROM orders o,
order_items oi
WHERE o.order_id = oi.order_id
AND o.salesman_id = (SELECT employee_id
FROM employees
WHERE
last_name = 'Marshall')
GROUP BY o.order_id
HAVING Count(customer_id) > 1)
GROUP BY c.customer_id,
c.name;
Database -
Not sure what I am doing wrong here.
That's a really contrived assignment... Here is one option:
select c.customer_id, c.customer_name, count(o.orderid) cnt
from customers c
left join orders o
on o.customer_id = c.customer_id
and (select last_name from employee e where e.employee_id = o.salesman_id) = 'Marshall'
where substr(c.name, 1, 7) = 'General' or substr(c.name, -8) = 'Electric'
group by c.customer_id, c.customer_name
having count(o.orderid) <> 1
The base idea is a left join. The where clause filters on the customer name - without like: you had that already.
To filter on the salesman name without an additional join, we use a correlated subquery in the on clause of the left join. There is no need to bring order_items, nor to select again from orders here.
Finally, the filtering on the order counts goes to the having clause.

Give the names of employees who sell the products of more than 10 suppliers

I am finding it difficult to write the query for the above question I have written the following query but it is returning all the rows
SELECT e.EmployeeID
FROM employees e
JOIN orders o ON e.EmployeeID = o.EmployeeID
JOIN order_details od ON o.OrderID = od.OrderID
JOIN Products p ON od.ProductID = p.ProductID
GROUP BY e.EmployeeID
HAVING COUNT(p.SupplierID) > 10
Your filtering condition is:
HAVING COUNT(p.SupplierID) > 10
COUNT() counts the number of non-NULL values. Presumably, all products have a supplier and you are using inner joins. So, all matching rows get counted. It is equivalent to:
HAVING COUNT(*) > 10
And this counts the number of order lines for a given employee.
You want to count distinct suppliers, not order lines. The simplest method is to use COUNT(DISTINCT):
HAVING COUNT(DISTINCT p.SupplierID) > 10
Because you are learning SQL, I would advise you to understand this version as well:
SELECT e.EmployeeID
FROM (SELECT e.EmployeeID, p.SupplierID, COUNT(*) as num_ordelines
FROM employees e JOIN
orders o
ON e.EmployeeID = o.EmployeeID JOIN
order_details od
ON o.OrderID = od.OrderID JOIN
Products p
ON od.ProductID = p.ProductID
GROUP BY e.EmployeeID, p.SupplierId
) es
GROUP BY EmployeeID
HAVING COUNT(SupplierID) > 10
This returns the same result set (assuming SupplierId is never NULL). The subquery has one row per employee/supplier. The outer query then counts these rows.

Match Id from one table with name from another and null values - mimer sql

I want to bring a column from another table that matches my id from the current table.
I've done this query:
SELECT dept, SUM(quantity) as TotalQuantity
FROM sale
GROUP BY dept
ORDER BY TotalQuantity;
Which gives me a total of items sold of a specific "department", now I want to bring the name of the department in there WITHOUT and WITH using explicit join. The department name is in another table called "dept" with column "name". Is there also possible the get the null values of my "sale" table as well?
SELECT dept, SUM(quantity) as TotalQuantity
FROM sale
GROUP BY dept
ORDER BY TotalQuantity;
The correct way is to use an explicit JOIN:
SELECT d.name, d.dept, SUM(s.quantity) as TotalQuantity
FROM dept d JOIN
sale s
ON d.dept = s.dept
GROUP BY d.name, d.dept
ORDER BY TotalQuantity;
If you want all rows in from dept, even those without sales, use a LEFT JOIN.
Note the use of table aliases and qualified column references. These are best practices when a query refers to more than one table.
I would never advise anyone to use a comma in a FROM clause. It is simply bad form. You can use a subquery if you want:
SELECT (SELECT d.name
FROM dept
WHERE d.dept = s.dept
) as name
s.dept, SUM(s.quantity) as TotalQuantity
FROM sale s
GROUP BY s.dept
ORDER BY TotalQuantity;
Or, alternatively:
SELECT d.dept, d.name,
(SELECT SUM(s.quantity)
FROM sales s
WHERE s.dept = d.dept
) as TotalQUantity
FROM dept d
ORDER BY TotalQuantity;
This is equivalent to the LEFT JOIN version -- it keeps all departments. With the right indexes (on sales(dept, quantity)), this can even be the fastest version.
I also want to present the departments that haven't sold any items as well with the null as the number of items they have sold:
Is this the correct way?
SELECT s.dept, d.name, SUM(s.quantity) as TotalQuantity
FROM sale s, dept d
WHERE d.number = s.dept AND s.quantity IS NULL
GROUP BY s.dept, d.name
ORDER BY TotalQuantity;
Using an explicit JOIN (assuming that column sale.dept references dept.id) :
SELECT d.id d.name, SUM(s.quantity) AS TotalQuantity
FROM dept AS d
LEFT JOIN sale AS s ON d.id = s.dept
GROUP BY d.id d.name
ORDER BY TotalQuantity
Because of the LEFT JOIN, departments without sales will also appear in the result list.
This would not be very relevant to do the same query using implicit, old-style JOIN, but that would be :
SELECT d.id d.name, SUM(s.quantity) AS TotalQuantity
FROM sale AS s, dept AS d
WHERE d.id = s.dept
GROUP BY d.id d.name,
ORDER BY TotalQuantity

SQL Join condition clause

I have database with as diagram shows (see picture below)
My task is to show total value of orders handled by each Employees.
I have SQL statement:
SELECT e.FirstName,
e.LastName,
SUM(od.Quantity * od.UnitPrice * (1-od.Discount))
FROM Orders AS o
JOIN Employees AS e
ON o.EmployeeID = e.EmployeeID
JOIN [Order Details] AS od
ON o.OrderID = od.OrderID
GROUP BY e.FirstName,e.LastName
I have problem with further steps. I need to limited results only for those employees which:
A) Have employees under them
B) Don't have any employees under them
I know It concern field ReportsTO in Employees table, but I don't know how get proper SQL clause. I am supposed to do with "EXISTS" or self-join ?
Thank You.
Yes, Just use Exists.
Where Exists(Select 1 from Employees where ReportsTo = e.EmployeeId)
Use a self join to try to find someone reporting to him
SELECT e.FirstName,
e.LastName,
SUM(od.Quantity * od.UnitPrice * (1-od.Discount))
FROM Orders AS o
INNER JOIN Employees AS e
ON o.EmployeeID = e.EmployeeID
LEFT JOIN Employees as under -- self join
ON e.EmployeeID = under.ReportTo
INNER JOIN [Order Details] AS od
ON o.OrderID = od.OrderID
GROUP BY e.FirstName,e.LastName
HAVING MAX(under.ReportTo) IS NULL -- If doesnt find a match mean no one subordinate
-- MAX(under.ReportTo) IS NOT NULL -- mean have at least one subordinate
With a self join you can potentially create duplicates which would be difficult to debug due to the GROUP BY. EXISTS with a correlated sub query in the WHERE clause would be how I would accomplish this.
SELECT *
FROM Employees e
WHERE EXISTS(
SELECT 1
FROM Employees _e
WHERE _e.ReportsTo = e.EmployeeID)
In your query:
SELECT e.FirstName,
e.LastName,
SUM(od.Quantity * od.UnitPrice * (1-od.Discount))
FROM Orders AS o
JOIN Employees AS e
ON o.EmployeeID = e.EmployeeID
JOIN [Order Details] AS od
ON o.OrderID = od.OrderID
WHERE /*NOT*/ EXISTS(
SELECT 1
FROM Employees _e
WHERE _e.ReportsTo = e.EmployeeID)
GROUP BY e.FirstName,e.LastName

Select IDs which do not JOIN

I want to get the list of ProductId which has not been ordered by an Employee.
I have this query which gives me all ProductId which has been ordered, but I want reverse of it:
SELECT distinct e.EmployeeID ,p.ProductID
FROM Products p JOIN OrderDetails od
ON od.ProductID=p.ProductID JOIN Orders o
ON o.OrderID=od.OrderID JOIN Employee e
ON e.EmployeeID=o.EmployeeID
order by e.EmployeeID
I'm not sure to understand your question, but if you want products without Employee associated you can try this :
SELECT distinct e.EmployeeID ,p.ProductID
FROM Products p
INNER JOIN OrderDetails od
ON od.ProductID=p.ProductID
INNER JOIN Orders o
ON o.OrderID=od.OrderID
LEFT JOIN Employee e
ON e.EmployeeID=o.EmployeeID
WHERE e.EmployeeID is NULL
order by e.EmployeeID
The idea is to select all the orders (INNER JOIN) also orders who haven't Employee associated (LEFT JOIN). Finally you filter on those which haven't association (IS NULL).