First is employee table, second is works_with table
emp_id is foreign key in works_with table.
What I want to do is to find first name & last name who has total sales more than 100,000.
For example, in first table, emp_id 105 person has 110,000 total sales.
So I want the output to be first name and last name of emp_id 102, 104, 105(whose total sales are more than 100,000).
I tried some nested queries and failed.
Failed code:
SELECT employee.first_name, employee.last_name
FROM employee
WHERE employee.emp_id IN(
SELECT works_with.emp_id, sum(total_sales)
FROM works_with
WHERE works_with.total_sales > 100000
GROUP BY works_with.emp_id);
when using WHERE-IN you must select only one column in subquery
and use aggregates functions for comparison in the HAVING clause they don't work with WHERE.
SELECT employee.first_name, employee.last_name
FROM employee
WHERE employee.emp_id IN(
SELECT works_with.emp_id
FROM works_with
GROUP BY works_with.emp_id
HAVING SUM(total_sales) > 100000
)
also you can use INNER JOIN to get same result
SELECT employee.first_name, employee.last_name,SUM(total_sales) as total_sales
FROM employee
INNER JOIN works_with ON employee.emp_id = works_with.emp_id
GROUP BY employee.emp_id
HAVING total_sales > 100000
Use a JOIN rather than WHERE-IN. And you need to test the sum of all total sales, not the individual total sales. You can do that using HAVING.
SELECT e.first_name, e.last_name
FROM employee AS e
JOIN works_with AS w ON e.emp_id = w.emp_id
GROUP BY e.emp_id
HAVING SUM(w.total_sales) > 100000
Related
Here's my orders table:
I want to select all orders excluding very first order of each customer (if customer has placed multiple orders).
So if a customer e.g. 215 has total 8 orders, then I will select his all last 7 orders excluding his very first order 70000 which was placed on 10 July 2017.
But if a customer e.g. 219 had placed only one order 70007, it must be selected by the query.
Using an anti-join approach:
SELECT o1.order_id, o1.customer_id, o1.order_date, o1.order_value
FROM orders o1
LEFT JOIN
(
SELECT customer_id, MIN(order_date) AS min_order_date, COUNT(*) AS cnt
FROM orders
GROUP BY customer_id
) o2
ON o1.customer_id = o2.customer_id AND
o1.order_date = o2.min_order_date
WHERE
o2.customer_site = 1 AND
(o2.customer_id IS NULL OR
o2.cnt = 1);
The idea here is to try to match each record in orders to a record in the subquery, which contains only first order records, for each customer. If we can't find a match, then such an order record cannot be the first.
You can try below -
select order_id,customer_id,order_date,order_Value
from tablename
group by order_id,customer_id,order_date,order_Value
having count(order_id)=1
union all
select order_id,customer_id,order_date,order_Value
from tablename a where order_date not in (select min(order_date) from tablename b
where a.customer_id=b.customer_id)
Solution
Dear #Tim Biegeleisen, your answer almost done. just add HAVING COUNT(customer_id)>1
So the query is below:
SELECT o1.order_id, o1.customer_id, o1.order_date, o1.order_value
FROM orders o1
LEFT JOIN (
SELECT customer_id, MIN(order_date) AS min_order_date
FROM orders
GROUP BY customer_id
HAVING COUNT(customer_id)>1
) o2
ON o1.customer_id = o2.customer_id AND
o1.order_date = o2.min_order_date
WHERE
o2.customer_id IS NULL;
I have 2 tables
the 1st one name is (employee) has 3 columns (emp_id, first_name, last_name)
the 2nd table name is (works_with) has also 3 columns (emp_id, client_id, total_sales)
in (works_with) table the same emp_id can be related to different client_id
I need to extract the (first_name) and (last_name) form (employee) table and their (total_sales) of more than 30000 from (work_with) table
I used this code to give me the (emp_id)* with the (total_sales) of more than 30000
SELECT SUM(works_with.total_sales), works_with.emp_id
FROM works_with
WHERE works_with.emp_id IN (SELECT works_with.emp_id
FROM works_with
WHERE works_with.total_sales > 30000)
GROUP BY works_with.emp_id;
and I used this code to give me the (first_name) and (last_name) of those (emp_id)*
SELECT employee.first_name, employee.last_name
FROM employee
WHERE employee.emp_id IN (SELECT works_with.emp_id
FROM works_with
WHERE works_with.total_sales > 30000);
is there a way to join the 2 codes or any other way to have the result that I want
Thank you
Are you just looking for a JOIN?
SELECT e.first_name, e.last_name, SUM(ww.total_sales)
FROM works_with ww JOIN
employee e
ON ew.emp_id = ww.emp_id
WHERE ww.emp_id IN (SELECT ww2.emp_id
FROM works_with ww2
WHERE ww.total_sales > 30000
)
GROUP BY e.emp_id, e.first_name, e.last_name;
The subquery is not needed. It is implementing this logic:
SELECT e.first_name, e.last_name, SUM(ww.total_sales)
FROM works_with ww JOIN
employee e
ON ew.emp_id = ww.emp_id
GROUP BY e.emp_id, e.first_name, e.last_name
HAVING MAX(ww.total_sales) > 30000;
However, I suspect that you want:
SELECT e.first_name, e.last_name, SUM(ww.total_sales)
FROM works_with ww JOIN
employee e
ON ew.emp_id = ww.emp_id
GROUP BY e.emp_id, e.first_name, e.last_name
HAVING SUM(ww.total_sales) > 30000;
Contributing here since I noticed an error in the other answer. See here for how different types of JOINs work: (Link).
SELECT
Employee.First_Name,
Employee.Last_Name,
SUM(WW.Total_Sales)
FROM
Works_With AS WW
INNER JOIN Employee AS Employee
ON Employee.EMP_ID = WW.EMP_ID
GROUP BY
Employee.EMP_ID,
Employee.First_Name,
Employee.Last_Name
HAVING
SUM(WW.Total_Sales) > 30000;
I have these tables : customers, customer_invoices, customer_invoice_details, each customer has many invoices, and each invoice has many details.
The customer with the ID 574413 has these invoices :
select customer_invoices.customer_id,
customer_invoices.id,
customer_invoices.total_price
from customer_invoices
where customer_invoices.customer_id = 574413;
result :
customer_id invoice_id total_price
574413 662146 700.00
574413 662147 250.00
each invoice here has two details (or invoice lines) :
first invoice 662146:
select customer_invoice_details.id as detail_id,
customer_invoice_details.customer_invoice_id as invoice_id,
customer_invoice_details.total_price as detail_total_price
from customer_invoice_details
where customer_invoice_details.customer_invoice_id = 662146;
result :
detail_id invoice_id detail_total_price
722291 662146 500.00
722292 662146 200.00
second invoice 662147 :
select customer_invoice_details.id as detail_id,
customer_invoice_details.customer_invoice_id as invoice_id,
customer_invoice_details.total_price as detail_total_price
from customer_invoice_details
where customer_invoice_details.customer_invoice_id = 662147;
result :
detail_id invoice_id detail_total_price
722293 662147 100.00
722294 662147 150.00
I have a problem with this query :
select customers.id as customerID,
customers.last_name,
customers.first_name,
SUM(customer_invoices.total_price) as invoice_total,
SUM(customer_invoice_details.total_price) as details_total
from customers
join customer_invoices
on customer_invoices.customer_id = customers.id
join customer_invoice_details
on customer_invoice_details.customer_invoice_id = customer_invoices.id
where customer_id = 574413;
unexpected result :
customerID last_name first_name invoice_total details_total
574413 terry amine 1900.00 950.00
I need to have the SUM of the total_price of the invoices, and the SUM of the total_price of the details for each customer. In this case I'm supposed to get 950 as total_price for both columns (invoice_total& details_total) but it's not the case. what am I doing wrong & how can I get the correct result please. The answers in similar topics don't have the solution for this case.
When you mix normal columns with aggregate functions (for example SUM), you need to use GROUP BY where you list the normal columns from the SELECT.
The reason for the excessive amount in total_price for invoices is that the SUM is also calculated over each detail row as it is part of the join. Use this:
select c.id as customerID,
c.last_name,
c.first_name,
SUM(ci.total_price) as invoice_total,
SUM((select SUM(d.total_price)
from customer_invoice_details d
where d.customer_invoice_id = ci.id)) as 'detail_total_price'
from customers c
join customer_invoices ci on ci.customer_id = c.id
where c.id = 574413
group by c.id, c.last_name, c.first_name
db-fiddle
I used join against sub queries and then did a sum on the sums
SELECT c.id as customerID,
c.last_name,
c.first_name
SUM(i.sum) as invoice_total,
SUM(d.sum) AS details_total
FROM customers c
JOIN (SELECT id, customer_id, SUM(total_price) AS sum
FROM customer_invoices
GROUP BY id, customer_id) AS i ON i.customer_id = c.id
JOIN (SELECT customer_invoice_id as id, SUM(total_price) AS sum
FROM customer_invoice_details
GROUP BY customer_invoice_id) AS d ON d.id = i.id
WHERE c.id = 574413
GROUP BY c.id, c.name
The issue is in the joining logic. The table customers is used as the driving table in the joins. But in the second join, you are using a derivative key column from the first join, to join with the third tables. This is resulting in a Cartesian output doubling the records from the result from the nth-1 join, which is leading to customer_invoices.total_price getting repeated twice, hence the rolled up value of this field is doubled.
At a high level I feel that the purpose of rolling up the prices is already achieved in SUM(customer_invoice_details.total_price).
But if you have a specific project requirement that SUM(customer_invoices.total_price) should also be obtained and must match with SUM(customer_invoice_details.total_price), then you can do this:
In a separate query, Join customer_invoice_details and customer_invoices. Roll up the pricing fields, and have a result such that you have only one record for one customer ID.
Then use this as a sub-query and join it with the customers table.
You are aggregating along multiple dimensions. This is challenging. I would suggest doing the aggregation along each dimension independently:
select c.id as customerID, c.last_name, c.first_name,
ci.invoice_total,
cid.details_total
from customers c join
(select ci.sum(ci.total_price) as invoice_total
from customer_invoices ci
group by ci.customer_id
) ci
on ci.customer_id = c.id join
(select ci.sum(cid.total_price) as details_total
from customer_invoices ci join
customer_invoice_details cid
on cid.customer_invoice_id = ci.id
group by ci.customer_id
) cid
on cid.customer_id = c.id
where c.id = 574413;
A faster version (for one customer) uses correlated subqueries:
select c.id as customerID, c.last_name, c.first_name,
(select ci.customer_id, sum(ci.total_price) as invoice_total
from customer_invoices ci
where ci.customer_id = c.id
) as invoice_total,
(select ci.customer_id, sum(cid.total_price) as details_total
from customer_invoices ci join
customer_invoice_details cid
on cid.customer_invoice_id = ci.id
where ci.customer_id = c.id
) as details_total
from customers c
where c.id = 574413;
i have employee and department table i need to find maximum average departmental salary.We can have two more than 1 maximum value.I tried the following query
select dept.name,avg(employee.sal)
from employee,dept
where dept.id=empolyee.id
group by dept.name
LIMIT 1
however i can manage only one maximum average salary, how can i get query more than one maximum value
You need to join with another query that gets the maximum average, then return all the rows with the same average.
SELECT t1.name, t1.avgSal
FROM (SELECT d.name, avg(e.sal) AS avgSal
FROM employee AS e
JOIN dept AS d ON d.id = e.dept_id
GROUP BY d.name) AS t1
JOIN (SELECT d.name, avg(e.sal) AS avgSal
FROM employee AS e
JOIN dept AS d ON d.id = e.dept_id
GROUP BY d.name
ORDER BY avgSal DESC
LIMIT 1) AS t2
ON t1.avgSal = t2.avgSal
I have 2 tables employees(id, first_name, last_name, salary, department_id_ and department(id, name) and I want to show number of employees in each department.
I have this question here:
SELECT department.name, COUNT(*) AS 'employees_number'
FROM department
LEFT JOIN employees
ON employees.department_id = department.id
GROUP BY department.id, department.name;
But for some reason, in departments where I have no people, it shows a number of employees as 1. Any idea why this is happening?
With an outer join you still get a result row when no match in the outer table is found. Only all employee column values are null then.
So rather than count the records, you want to count matched records, i.e. where an employee was found and its data is not null. So Count a column in the employee table (nulls are not counted, when counting a column or expression). E.g. use COUNT(e.department_id) or COUNT(e.id):
SELECT d.name, COUNT(e.id) AS employees_number
FROM department d
LEFT JOIN employees e ON e.department_id = d.id
GROUP BY d.id, d.name;
What I prefer though, is to aggregate/count before joining. The query looks a bit more complicated, but is less prone to errors on future query changes:
SELECT d.name, COALESCE(e.how_many, 0) AS employees_number
FROM department d
LEFT JOIN
(
SELECT department_id, COUNT(*) AS how_many
FROM employees
GROUP BY department_id
) e ON e.department_id = d.id;
As it's one aggregated column only you want, you can move the subquery to your SELECT clause and get thus a simpler query:
SELECT
d.name,
(
SELECT COUNT(*)
FROM employees e
WHERE e.department_id = d.id
) AS employees_number
FROM department d;
Using SUM instead of COUNT also can give you what you want:
SELECT
department.name,
SUM(CASE WHEN employees.id IS NOT NULL THEN 1 ELSE 0 END) AS 'employees_number'
FROM department
LEFT JOIN employees
ON employees.department_id = department.id
GROUP BY department.id, department.name;
SQL Fiddle:
http://sqlfiddle.com/#!9/8b8976/1
select department.name, count(employee.id) as co from
department left join employee on
department.id = employee.dept_id group by department.name
order by co desc, department.name asc