Slightly complex MySQL query - mysql

employees
e_id first last
1 John Smith
2 Bob Smith
3 Alex Smith
4 John Doe
5 Ron Doe
clockpunch
e_id time for adjustment
1 0650 in early
3 0710 in late
4 0725 in early
1 1100 lunch ---
2 1150 in late
2 1400 lunch ---
4 1320 out ---
I need a SINGLE query that will list all employee names, along with a count of how many times that user has been early, descending order by the count of times early. How would this be done ?

select a.first,a.last,sum(case b.adjustment when 'early' then 1 else 0 end) as ct
from employees a, clockpunch b where a.e_id=b.e_id
group by a.first, a.last

This might work (untested)
select first,last,count(*) from employees e, clockpunch c
where e.e_id = c.e_id and adjustment = 'early'
group by first,last
order by count(*) desc

Related

Query that provides the names of the recruiters that hire more than 3 employees, and the number of employees that were not hired by a recruiter

I'm a bit stuck on this question and was hoping for some help. Here's where I'm at currently.
I have this TEST table of Names. Each Person can either be a recruiter or an employee. The number in Recruited_by is associated with the person_id.
Person_id Name Recruited_by
1 Jean Grayson 1
2 Paul Smith 7
3 John Do Null
4 Alex Lee 7
5 Lisa Kim 7
6 Bob Thompson 3
7 Mike Keen Null
8 Raymond Red 3
9 Alisson Jones 1
10 Kate James 3
Here is the query I have so far which I'm trying to the names of the recruiters that hire more than 3 employees (which will return nothing in this case) and the number of employees that were NOT recruited by anyone (which would be the NULL names).
SELECT T.Name as Employees, COUNT(T1.Name) as Not_hired
FROM Test AS T
WHERE COUNT(T1.Name) IS NULL
LEFT OUTER JOIN Test AS T1
ON T.Recruited_by = T1.Person_id
GROUP BY T.Name
HAVING COUNT(T1.Name) > 3
However this query is returning nothing when I should expect it to return the number of employees who were not hired by a recruiter!
If you want in the results only 1 row with 2 columns then you can do a LEFT join of the table to a query that aggregates to get the ids of the persons that hired more than 3 persons and aggregate again to get the number of persons that were not recruited by anyone:
SELECT GROUP_CONCAT(CASE WHEN t2.Recruited_by IS NOT NULL THEN t1.Name END ORDER BY t1.Name) names,
SUM(t1.Recruited_by IS NULL) total_not_recruited
FROM Test t1
LEFT JOIN (
SELECT Recruited_by
FROM Test
GROUP BY Recruited_by
HAVING COUNT(*) > 3
) t2 ON t2.Recruited_by = t1.Person_id;
You will get the names of the persons that hired more than 3 persons (if they exist) as a comma separated list.
See the demo.

Can this be done with a subquery?

I have a table looking like this:
Team Name Points
A Peter 26
A John 18
A Carl 20
A Robert 32
A Mike 10
B Tom 22
B Michael 28
B Tina 18
B Donald 35
B Jeff 20
I want to get a result from the query that will give me the best 3 users from a team and the SUM of the point from the 3 highest users.
For team A the 3 highest scores are Robert (32), Peter (26) and (Carl (20) which is a total of 78 points.
For team B the highest 3 scores are Donald (35), Michael (28) and Tom (22) which is a total of 85 points
So it must be something like this:
Place Team Points
1 B 85
2 A 78
I have tried something like this:
SELECT points, user FROM table ORDER BY points DESC, LIMIT 3
That will give me the 3 users with the highest points but I want also the SUM of these 3 users and these records must be per team.
I think it must be done with a subquery, is this correct?
SELECT team,SUM(points) sp FROM
(
(
SELECT * FROM `table` WHERE team = "A" ORDER BY points DESC LIMIT 3
)
UNION ALL
(
SELECT * FROM `table` WHERE team = "B" ORDER BY points DESC LIMIT 3
)
)
AS dbx
GROUP BY team
ORDER BY sp DESC
Explaination:
Your Data:
Get Highest 3 from both Team (A and B).
And then, sum After join them All.
Result:

MySQL join tables for counts with multiple conditions

Trying to create a report across 3 tables - company, account, user. For each company, there's an ID in account. Each user has an account. I can get totals easily enough, but I need to add count of how many users out of the total are registered (username is not null).
SELECT c.c_name, c.c_groupnumber, count(a.a_userid) AS TotalCount
FROM company c
LEFT JOIN account a ON c.c_groupnumber = a.a_groupnumber
WHERE a.a_deleted IS NULL
GROUP BY c.c_groupnumber
HAVING TotalCount > 0;
How can I add in a condition that gives me a count of user.u_username not null while maintaining my TotalCount? The link between account and user is
a.a_userid = user.u_userid
tbl.company
c_id, c_groupnumber, c_name
1 1234 widgets, inc.
2 5678 joe's garage
tbl.user
u_userid, u_username, u_name
1 bill Bill Smith
2 frank Frank Johnson
3 NULL Jane Doe
4 mary Mary Stack
5 NULL Steve Spot
tbl.account
a_id, a_userid, a_groupnumber
100 1 1234
101 2 5678
102 3 5678
103 4 1234
104 5 1234
So using the above very simplified table example, company "Widget's Inc." has 3 employees (bill smith, mary stack and steve spot), and of those 3 2 have registered (bill and mary), while steve has not (username is null).
Joe's Garage has 2 employees - Frank and Jane, and Frank has registered, while Jane has not.
I'd love to generate a report something like this:
Group Company Total Emp Reg Emp
1234 Widgets Inc 3 2
5678 Joe's Garag 2 1
Hopefully that makes the question clearer?
What if you get the count of username and then perform a JOIN with that like
SELECT c.c_name, c.c_groupnumber, count(a.a_userid) AS TotalCount,
xxx.username_count
FROM company c
LEFT JOIN account a ON c.c_groupnumber = a.a_groupnumber
LEFT JOIN ( select u_userid, count(u_username) username_count
from `user`
group by u_userid ) xxx ON a.a_userid = xxx.u_userid
WHERE a.a_deleted IS NULL
GROUP BY c.c_groupnumber
HAVING TotalCount > 0;

SELECT sql with four different tables with primary key and foreign key

For my database, having these four table
First one, DEPARTMENT
//DEPARTMENT
D# DNAME
------------------
1 RESEARCH
2 IT
3 SCIENCE
Second one, EMPLOYEE
//Employee
E# ENAME D#
-----------------------
1 ALI 1
2 SITI 2
3 JOHN 2
4 MARY 3
5 CHIRS 3
Third, PROJECT
//PROJECT
P# PNAME D#
-----------------------
1 Computing 1
2 Coding 3
3 Researching 3
Fourth, WORKSON
//WORKSON
E# P# Hours
--------------------
1 1 3
1 2 5
4 3 6
So my output should be something like
E# ENAME D# TOTAL HOURS/W
--------------------------------------------
1 ALI 1 8
2 SITI 2 0
3 JOHN 2 0
4 MAY 3 6
5 CHIRS 3 0
Display 0 because the employee has no project to works on.
my currently statement using
SELECT E#,ENAME,D# and sum(Hours) as TOTAL HOURS/W
FROM EMPLOYEE,PROJECT,WORKSON
WHERE EMPLOYEE.P#
no idea how should it select
You should use an left join like this. You only need 2 tables employee and workson.
Try this query:
SELECT e_tbl.E#, e_tbl.ENAME, e_tbl.D#,
coalesce(SUM(w_tbl.Hours), 0) as "Total Hours/W"
FROM
EMPLOYEE e_tbl LEFT JOIN WORKSON w_tbl
ON e_tbl.E# = w_tbl.E#
GROUP BY e_tbl.E#
You need to use GROUP BY and JOINS , in order to achieve your output
SELECT E.E#,
E.ENAME,
E.D#,
sum(Hours) AS TOTAL HOURS/W
FROM Employee AS E
JOIN WORKSON AS W ON E.E# = W.E#
GROUP BY E.E#,
E.ENAME,E.D#
Use this :)
With the given output you do not need to join all the tables, and this could be done by joining employee and works on as
select
e.`E#`,
e.ENAME,
e.`D#`,
coalesce(tot,0) as `TOTAL HOURS/W`
from Employee e
left join
(
select `E#`,
sum(Hours) as tot
from WORKSON
group by `E#`
)w
on w.`E#` = e.`E#`
group by e.`E#`
DEMO

mysql select in another select group: how many people in downline?

Hello i've a table similar to this one:
id sponsor name
------------------------
1 0 Sasha
2 1 John
3 1 Walter
4 3 Ashley
5 1 Mark
6 4 Alexa
7 3 Robert
8 3 Frank
9 4 Marika
10 5 Philip
11 9 Elizabeth
when i choose an ID (call it MYCHOICE) i want know all the name of people who has sponsor like MYCHOICE... is simply:
select * from tablename where sponsor=MYCHOICE
but... here is the problem... i would know how many people there is in the downline of this results... so... how many records there are with sponsor like each id.
if i choose id 1 result should be
id name downline
----------------------
2 John 0 (noone with sponsor=2)
3 Walter 3 (3 with sponsor=3: ashley, robert, frank)
5 Mark 1 (1 with sponsor=5: philip)
if i choose id 4 result should be
id name downline
----------------------
6 Alexa 0
9 Marika 1 (1 with sponsor=9: Elizabeth)
i try this "bad solution" if mychoice is 1
select sponsor,count(*) as downline from tablename where sponsor in
(select id from tablename where sponsor=1) group by sponsor order by
downline desc
result of this query is
sponsor downline
---------------------
3 3
5 1
there are 2 problems:
- names are not rights and is not that i want
- the count 0 "2|John|0" in the example dont appears
thank u for advice and help, sorry for english,
N.
SELECT child.id,
child.name,
COUNT(grandchild.sponsor) downline
FROM TableName child
INNER JOIN TableName parent
ON child.sponsor = parent.id AND
parent.id = ? -- << user choice
LEFT JOIN TableName grandchild
ON child.id = grandchild.sponsor
GROUP BY child.id, child.name
SQLFiddle Demo
As you can see, the table is joined to itself twice. The first join that uses INNER JOIN gets the records associated with the Sponsor which is your user_choice. The second join which uses LEFT JOIN gets all the records associated with records from your user_choice.