This is my simplified table
year | teacher
1 | john
2 | john
2 | sam
3 | john
3 | simon
When I run the query below
SELECT year, teacher FROM table1 GROUP BY year
It gives me the result :
year | teacher
1 | john
2 | john
3 | john
In this case, year column is fine as it shows all distinct value, however teacher column is still repeated. I wish to have distinct values on teacher columns too.
Output I am looking for :
year | teacher
1 | john
2 | sam
3 | simon
This query is not valid SQL (even if MySQL happens to accept it):
SELECT year, teacher
FROM table1
GROUP BY year;
You need an aggregation function around teacher:
SELECT year, MAX(teacher)
FROM table1
GROUP BY year;
That said, this doesn't do what you want. That is hard to do in a single query. Instead, use two queries:
SELECT DISTINCT year FROM table1;
SELECT DISTINCT teacher FROM table1;
Related
Suppose I have a SQL table "Company" with three columns: "department_id", "employee", "job". Something like this:
DEPARTAMENT_ID | EMPLOYEE | JOB
--------------------------------------
1 | Mark | President
1 | Robert | Marketing Manager
1 | Rose | Administration Assitant
2 | Anna | Programmer
2 | Michael | Programmer
2 | Celia | Sales Manager
3 | Jhon | Sales Manager
3 | Donna | Programmer
3 | David | Marketing Manager
I would like to write a query that returns the departments id where at least 50% of their jobs are the same.
Result i need in my example would be just:
DEPARTAMENT_ID |
--------------------------------------
2 |
How do I write this SQL query? I think i tried all kind of stuff but i dont get it :(.
This is a bit tricky. You need to compare the total number of people on a job in a department to the total number. So, one method uses two aggregations:
select department_id
from (select department_id, count(*) as numemp
from t
group by department_id
) d join
(select department_id, max(numemp) as numemp
from (select department_id, job, count(*) as numemp
from t
group by department_id, job
) d
group by department_id
) dj
on d.numemp <= 2 * dj.numemp;
You might get duplicates if you have one department that is exactly split between two jobs. In that case, use select distinct.
(SELECT childinfo.first,childinfo.last,COUNT(clubinfo.club) AS clubs_per_student FROM clubinfo
LEFT JOIN childinfo
ON childinfo.child_id=clubinfo.child_id
GROUP BY concat(studentinfo.first,' ',studentinfo.last)
)
Above is the query that I have written to combine the tables childinfo (containing the columns child_id, first name, and last name) and clubinfo (containing columns child_id and club). The above query would produce a table that is something like this:
first | last | sports_per_child
Sally | Jones | 2
Phil | Jones | 1
Jane | Doe | 1
John | Doe | 1
What I am looking to do is use the results of that query to produce a report of the total number of students who are in a particular number of clubs. So, for example, the table above would produce a report that there are 3 students that are in 1 club and 1 student that is in 2 clubs.
Any ideas on how to write a query that uses my previously written query as a subquery to accomplish this?
You just need to get a count and group by sports_per_child:
SELECT sports_per_child, count(*) FROM
(subquery) AS S
group by sports_per_child
I recently got this question on interview which I failed to answer. The question was to list the number of duplicates that appear in a column employer like from this table
id | employer | employee
1 | isro | dude1
2 | isro | dude 2
3 | cnd | dude 3
4 | df | dsfdef
5 | dfdf | dfdfd
...
so the result should be like
isro = 2
df = 4
dfsf = 6
how do i achieve this?
I know there is count(*) which i could use with select statement with where clause, but how do i achieve the above result.
The HAVING clause can be used to filter on aggregated values:
SELECT employer, COUNT(*)
FROM yourTable
GROUP BY employer
HAVING COUNT(*) > 1
assuming TableName is the name of the table you want to select from, this would be your answer.
SELECT employer, count(employer)
FROM TableName
GROUP BY employer
HAVING COUNT(*) > 1
here is an answer to a very similar question that has some more info for you.
How to count occurrences of a column value efficiently in SQL?
I am working on a PHP/MySQL timesheet system, and the report I want to create selects all employees who have worked less than the required amount of time between two dates.
The employee's time is stored in hours and minutes (INT), but I am only concerned with the hours.
The employee table looks like:
ID | Name
1 | George
2 | Fred
The timesheet_entry table:
ID | employeeID | hour | date
1 | 1 | 2 | 2013-07-25
2 | 2 | 4 | 2013-07-25
3 | 1 | 3 | 2013-07-25
So if I SELECT employees who have worked less than 5 hours (PHP variable hrsLimit) on 2013-07-25, it should return 2 Fred, as George has worked a total of 5 hours on that date.
I have a HTML form so the user can set the variables for the query.
I have tried:
SELECT employeeid,
employeename
FROM employee
JOIN timesheet_entry tse
ON tse.tse_employeeid = employeeid
AND Sum(tse.hour) < $hrslimit
I have not worried about the date yet.
The confusing bit here is that we are joining two tables. Perhaps I should select the hours and put the SUM clause at the end in a WHERE instead?
You need to group data and then place SUM condition in the HAVING part of the query.
select employee.id,
employee.Name,
Date,
sum(`hour`)
from timesheet_entry
join employee on timesheet_entry.employeeID=employee.ID
group by timesheet_entry.employeeID,date
having sum(`hour`)<$hrslimit
SQLFiddle demo
assume following data:
Data:
id | date | name | grade
--------+---------------+-----------+---------------
1 | 2010/12/03 | Mike | 12
2 | 2010/12/04 | Jenny | 12
3 | 2010/12/04 | Ronald | 15
4 | 2010/12/03 | Yeni | 11
i want to know who has the best grade in each day, something like this:
Desired Result:
id | date | name | grade
--------+---------------+-----------+---------------
1 | 2010/12/03 | Mike | 12
3 | 2010/12/04 | Ronald | 15
i thought query should look like this:
SELECT name FROM mytable
GROUP BY date
ORDER BY grade DESC
but it returns something like this:
Current Unwanted Result:
id | date | name | grade
--------+---------------+-----------+---------------
1 | 2010/12/03 | Mike | 12
2 | 2010/12/04 | Jenny | 12
i searched and i found the reason:
GROUP BY happens before ORDER BY so it does not see and can't apply ORDER.
so how can i apply ORDER on GROUP BY?
Note: please keep in mind that i need the most simple query, because my query is actually very complex, i know i can achieve this result by some subquery or JOINing, but i want to know how to apply ORDER to GROUP BY. thanks
I used Oracle for this example, but the SQL should work in mysql (you may need to tweak the to_date stuff to work with mysql). You really need a subquery here to do what you are asking.
CREATE TABLE mytable (ID NUMBER, dt DATE, NAME VARCHAR2(25), grade NUMBER);
INSERT INTO mytable VALUES(1,to_date('2010-12-03','YYYY-MM-DD'),'Mike',12);
INSERT INTO mytable VALUES(1,to_date('2010-12-04','YYYY-MM-DD'),'Jenny',12);
INSERT INTO mytable VALUES(1,to_date('2010-12-04','YYYY-MM-DD'),'Ronald',15);
INSERT INTO mytable VALUES(1,to_date('2010-12-03','YYYY-MM-DD'),'Yeni',11);
SELECT id
, dt
, name
, grade
FROM mytable t1
WHERE grade = (SELECT max(grade)
FROM mytable t2
WHERE t1.dt = t2.dt)
ORDER BY dt
Results:
ID DT NAME GRADE
1 12/3/2010 Mike 12
2 12/4/2010 Ronald 15
I know you said you wanted a GROUP / ORDER only solution but you will need to use a subquery in this instance. The simplest way would be something like this:
SELECT id, date, name, grade
FROM mytable t1
WHERE grade =
(SELECT MAX(t2.grade) FROM mytable t2 WHERE t1.id = t2.id)
This would show multiple students if they shared the highest grade for the day.