I have a regular table with employee info:
ID int
NAME varchar
Besides that I have a table with purchases. The employee id is listed here
again either in the column seller or contractor. It is possible that a employee
has not done any sales. It is also possible that no contractor or no seller is involved.
EMPLOYEES
ID NAME
1 Bill
2 Cliff
3 Mary
4 Jon
PURCHASES
ID SELLER CONTRACTOR
1 1 2
2 1
3 2 1
4 2 3
I want to get the list with the employee id and name and information if
this employee is listed in the seller and/or contractor columns. So basically
if this employee has done any sales.
ID NAME SALES
1 Bill 1
2 Cliff 1
3 Mary 1
4 Jon 0
What I get is double lines when employees are listed in multiple sales. I have tries numerous LEFT JOIN statements.
You can do it with EXISTS:
select e.*,
exists (select 1 from purchases where e.id in (seller, contractor)) sales
from employees e
See the demo.
Or with a LEFT JOIN and aggregation:
select e.id, e.name, max(p.id) is not null sales
from employees e left join purchases p
on e.id in (p.seller, p.contractor)
group by e.id, e.name
See the demo.
Results:
| ID | NAME | sales |
| --- | ----- | ----- |
| 1 | Bill | 1 |
| 2 | Cliff | 1 |
| 3 | Mary | 1 |
| 4 | Jon | 0 |
You could use LEFT JOIN and COUNT based on column from "outer table":
SELECT e.ID, e.name, COUNT(p1.seller) AS cnt_seller, COUNT(p2.contractor) AS cnt_contractor
FROM Employees e
LEFT JOIN Purchases p1
ON e.ID = p1.seller
LEFT JOIN Purchases p2
ON e.ID = p2.contractor
GROUP BY e.ID, e.name
Related
I have two tables, one for employees which has id, name and company columns and another table for survey results which has employee_id, questions_id, answer as one employee to many results.
|---------------------|
| id | name | company |
|---------------------|
|-----------------------------------------|
| id | employee_id | question_id | answer |
|-----------------------------------------|
I want to Select total number of employees for each company, and total participants from each company in the survey.
I tried the following query, but it's taking too much time to execute:
SELECT employees.company as x, COUNT(DISTINCT (results.employee_id)) "Total Surveys", (SELECT COUNT(employees.id) FROM employees WHERE company = x) "Headcount"
FROM results
JOIN employees ON results.employee_id = employees.id
GROUP BY employees.company
Result
|--------------------------------|
| x | Total Surveys | Headcount |
|--------------------------------|
| C1 | 15 | 3 |
| C2 | 10 | 5 |
|--------------------------------|
SQL Fiddle
Any recommendations?
You can get the results you want by a LEFT JOIN from employees to results; then you can count both values without a subquery:
SELECT e.company,
COUNT(DISTINCT r.employee_id) AS `Total Surveys`,
COUNT(DISTINCT e.id) AS `HeadCount`
FROM employees e
LEFT JOIN results r ON r.employee_id = e.id
GROUP BY e.company
Demo on SQLFiddle
I've two tables.
User(id,name)
Finance(id,item_id,amount,user_id)
My use case is
users are the employees (sales guys) of the organization.
When they sell an item finance table get updated with a new record of that sold item's serial id.
I want to get the user names along with the total value of the sales they made.
User
id | name
1 | Dinesh
2 | Pathum
3 | Naveed
Finance
id | item_id | amount | user_id
1 | 1 | 2000 | 1
2 | 2 | 2000 | 1
3 | 3 | 1000 | 3
4 | 4 | 500 | 3
Expected output
Dinesh 4000
Pathum 0
Naveed 1500
How do I achieve this using MySQL?
The query is like the following:
SELECT u.name as 'Agent Name',
if(sum(f.amount) IS NULL, 0,sum(f.amount)) as Total,
f.createdAt
FROM users u LEFT JOIN finance f
ON u.id = f.user_id
GROUP BY u.id, u.name, f.createdAt
ORDER BY f.createdAt DESC
Here is a working SQL Fiddle.
Join em, group em, sum em.
SELECT usr.name AS UserName, COALESCE(SUM(fin.amount),0) AS TotalAmount
FROM `User` usr
LEFT JOIN `Finance` fin ON fin.user_id = usr.id
GROUP BY usr.id, usr.name
ORDER BY usr.id;
Test on db<>fiddle here
Another way:
SELECT Name,SUM(IFNULL(amount,0)) AS "Total" FROM (SELECT Name,amount FROM user LEFT JOIN finance ON user.id=finance.user_id) a GROUP BY Name;
In a MySQL database I have the following tables:
customers
CUSTOMER_ID | NAME
---------------------------
1 | John Doe
2 | Peter Jones
3 | David Smith
products
PRODUCT_ID | DESCRIPTION
---------------------------
1 | Toothbrush
2 | Shaving cream
3 | Deodorant
customer_product
CUSTOMER_ID | PRODUCT_ID
---------------------------
1 | 2
1 | 3
2 | 1
3 | 1
3 | 2
The table customer_product is a pivot table. When a customer orders a product, it will be logged there.
My question is: how can I select all customers that didn't ordered a certain product?
So for example, I want to retrieve all customers that never ordered a Toothbrush.
You can use NOT EXISTS:
SELECT CUSTOMER_ID,NAME
FROM customers AS c
WHERE NOT EXISTS (
SELECT 1
FROM customer_product AS cp
INNER JOIN products AS p
ON cp.PRODUCT_ID= p.PRODUCT_ID
WHERE p.DESCRIPTION = 'Toothbrush' AND cp.CUSTOMER_ID = c.CUSTOMER_ID)
Here is another way that will work for you
select c.customer_id,c.Name from customers c
where c.customer_id not in
(select c.customer_id from customers c
left join customer_product cp on c.customer_id = cp.customer_id
inner join products p on cp.product_id = p.product_id
where p.description ='toothbrush'
) ;
I have 2 tables that I am trying to join but I am not sure how to make it the most time efficient.
Tasks Table:
nid | created_by | claimed_by | urgent
1 | 11 | 22 | 1
2 | 22 | 33 | 1
3 | 33 | 11 | 1
1 | 11 | 43 | 0
1 | 11 | 44 | 1
Employee Table:
userid | name
11 | EmployeeA
22 | EmployeeB
33 | EmployeeC
Result I am trying to get:
userid | created_count | claimed_count | urgent_count
11 | 3 | 1 | 3
22 | 1 | 1 | 2
33 | 1 | 1 | 2
created_account column will show total # of tasks created by that user.
claimed_count column will show total # of tasks claimed by that user.
urgent_count column will show total # of urgent tasks (created or claimed) by that user.
Thanks in advance!
I would start by breaking this up into pieces and then putting them back together. You can get the created_count and claimed_count using simple aggregation like this:
SELECT created_by, COUNT(*) AS created_count
FROM myTable
GROUP BY created_by;
SELECT claimed_by, COUNT(*) AS claimed_count
FROM myTable
GROUP BY claimed_by;
To get the urgent count for each employee, I would join the two tables on the condition that the employee is either the created_by or claimed_by column, and group by employee. Instead of counting, however, I would use SUM(). I am doing this because it appears each row will be either 0 or 1, so SUM() will effectively count all non-zero rows:
SELECT e.userid, SUM(t.urgent)
FROM employee e
JOIN task t ON e.userid IN (t.created_by, t.claimed_by)
GROUP BY e.userid;
Now that you have all the bits of data you need, you can use an outer join to join all of those subqueries to the employees table to get their counts. You can use the COALESCE() function to replace any null counts with 0:
SELECT e.userid, COALESCE(u.urgent_count, 0) AS urgent_count, COALESCE(crt.created_count, 0) AS created_count, COALESCE(clm.claimed_count, 0) AS claimed_count
FROM employee e
LEFT JOIN(
SELECT e.userid, SUM(t.urgent) AS urgent_count
FROM employee e
JOIN task t ON e.userid IN (t.created_by, t.claimed_by)
GROUP BY e.userid) u ON u.userid = e.userid
LEFT JOIN(
SELECT claimed_by, COUNT(*) AS claimed_count
FROM task
GROUP BY claimed_by) clm ON clm.claimed_by = e.userid
LEFT JOIN(
SELECT created_by, COUNT(*) AS created_count
FROM task
GROUP BY created_by) crt ON crt.created_by = e.userid;
Here is an SQL Fiddle example.
This question already has answers here:
Sum total of table with two related tables
(2 answers)
Closed 9 years ago.
I have 4 tables, with the relevant columns summarized here:
customers:
id
name
credits:
id
customer_id # ie customers.id
amount
sales:
id
customer_id # ie customers.id
sales_items:
id
sale_id # ie sales.id
price
discount
The idea is that customers lists all of our customers, credits lists each time they have paid us, sales lists each time they have bought things from us (but not what things they bought) and sales_items lists all of the items they bought at each of those sales. So you can see that credits and sales both relate back to customers, but sales_items only relates back to sales.
As an example dataset, consider:
customers:
id | name
5 | Carter
credits:
id | customer_id | amount
1 | 5 | 100
sales:
id | customer_id
3 | 5
sales_items:
id | sale_id | price | discount
7 | 3 | 5 | 0
8 | 3 | 0 | 0
9 | 3 | 10 | 0
I have tried this in MySQL:
SELECT c.*,
SUM( cr.amount ) AS paid,
SUM( i.price + i.discount ) AS bought
FROM customers AS c
LEFT JOIN sales AS s ON s.customer_id = c.id
LEFT JOIN sales_items AS i ON i.sale_id = s.id
LEFT JOIN credits AS cr ON cr.customer_id = c.id
WHERE c.id = 5
But it returns:
id | name | paid | bought
5 | Carter | 300 | 15
If I omit the SUM() functions, it returns:
id | name | paid | bought
5 | Carter | 100 | 5
5 | Carter | 100 | 0
5 | Carter | 100 | 15
So it looks like it's returning one row for every record matched in sales_items, but it's filling in the amount column with same value from credits each time. I see that this is happening, but I'm not understanding why it's happening.
So, two questions:
1. What is happening that it's smearing that one value through all of the rows?
2. What SQL can I throw at MySQL so that I can get this back:
id | name | paid | bought
5 | Carter | 100 | 15
I know that I could break it all up in subqueries, but is there a away to do it just with joins? I was hoping to learn a thing or two about joins as I tackled this problem. Thank you.
Edit: I created an SQL Fiddle for this: http://sqlfiddle.com/#!2/0051b/1/0
select distinct (c.id, c.name), sum(i.price+i.discount) AS bought, cr.amount AS paid
from customer c, credits cr, sales s, sales_items i
where s.customer_id = c.id
and i.sale_id = s.id
and cr.customer_id = c.id and c.id = 5
group by c.id, c.name;
I'm not very sure, but try this. Use group by; that is surely the solution.
Please try this
SELECT c.*,( SELECT SUM( cr.amount ) FROM customer c INNER JOIN credits cr ON
cr.customer_id = c.id WHERE c.id = 5 GROUP BY cr.id ) AS paid
,SUM( i.price + i.discount ) AS bought
FROM customers AS c INNER JOIN sales s ON s.customer_id = c.id
INNER JOIN sales_items i ON i.sale_id = s.id
INNER JOIN credits cr ON cr.customer_id = c.id
WHERE c.id = 5 GROUP BY s.id,cr.id