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
Related
Im having a problem with an aggregate function in mysql.
As an example I have this table layout. It gets filled with data every x minutes.
Company | Employee | Room | Temperature
---------------------------------------
A | Mike | 301 | 20
A | Mike | 301 | 30
A | Mike | 301 | 30
A | Mike | 402 | 40
A | Lisa | 402 | 10
Now in my query I'm grouping Company + Employee into one result and I'm looking for the count of the maximum occurrences of the Room value while still aggregating other values like temperature.
SELECT
Company,
Employee,
??? as Room,
AVG(Temperature) as Temperature
FROM
example_table
GROUP BY
Company,
Employee
In this example the room 301 appears 3 times for Mike which should output 3 in the aggregate function. Since the data is on a set interval it is basically the maximum length of a stay in a room for this employee. I'm looking for a result like this
Company | Employee | Room | Temperature
---------------------------------------
A | Mike | 3 | 30
A | Lisa | 1 | 10
I feel like I'm missing something but so far I have found nothing which worked in a query for me. I can group_concant the rooms and solve this with 2 lines of code in php, but the actual data is gigabytes which I don't want to send to a script. Performance of the database query doesn't matter. MySQL 8 is available.
edit: I've changed the example to make sure COUNT(DISTINCT Room) doesn't accidentally give the correct result, because it's not what I'm looking for.
SELECT Company, Employee
, MAX(roomOccurrence) AS Room
, AVG(roomTemp * roomOccurrence) AS Temperature
FROM ( SELECT Company, Employee, Room
, COUNT(*) AS roomOccurrence, AVG(Temperature) AS roomTemp
FROM example_table
GROUP BY Company, Employee, Room
) AS subQ
GROUP BY Company, Employee
;
Note the outer temperature average weights the temperature average from the inner query.
Alternatively, you could SUM the temps in the subquery...and then divide the SUM of the SUM by the SUM of the room COUNT; but's it should be the same either way. I would at best expect minor performance differences, and not sure if either way would be consistently faster.
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;
I am looking for an SQL query to give me a list of duplicate entries in a table. However, there are 3 different columns to take into account. First is an ID, Second is a Name, and third is a Date. The situation is that there are multiple Names that are assigned with the same ID, and there are multiple records of those in a day, which makes THOUSANDS of different records per day.
I already filtered it so that only results for the past 7 days will show, but the amount of records is still too much for me to extract. I just want to decrease the number of rows in the output order to properly extract the results.
Sample
|--id-|--name--|-------date------|
| 1 | a |5-9-2015, 10:00am|
| 1 | a |5-8-2015, 10:02am|
| 1 | a |5-8-2015, 11:00am|
| 1 | b |5-8-2015, 10:00am|
| 1 | b |5-8-2015, 10:02am|
| 1 | c |5-8-2015, 10:00am|
| 2 | d |5-8-2015, 10:00am|
expected output
|--id-|--name--|
| 1 | a |
| 1 | b |
| 1 | c |
| 2 | d |
Inclusion of entries without any duplicates are fine. The important thing is to only return a single record of a unique id-name combination for a day.
Thanks in advance for any help that you can give.
You can get the combinations as:
select distinct id, name
from sample;
If you want duplicates, using group by and having:
select id, name
from sample
group by id, name
having count(*) > 1;
EDIT:
If you want this by date, then add date(date) to the group by and perhaps select clauses.
To return single id-name data per day you can use this:
select id, name
from tab
group by id, name, date(date)
The DATE() function extracts the date part of a date or date/time expression.
select id,name
from sample
group by id,name,DATE(date)
having count(*)>1;
I have answered and read many question on getting the greatest-n-per-group but now find myself needing the opposite.
I have a result set that shows students, date, and project that represent which students worked on a project on a given day.
I would like to see rows where multiple students worked on a project for that day. So if my result set looks like this:
| student | date | project |
+---------+------------+---------+
| 1 | 2014-12-04 | 1 |
| 2 | 2014-12-04 | 1 |
| 3 | 2014-12-04 | 1 |
| 1 | 2014-12-03 | 1 |
I would only like to see the first three rows, so I can see that students 1,2,3 worked together on the same project on the same day. I could filter like this:
GROUP BY date, project
HAVING COUNT(*) > 1
But then only one row will be returned.
you can use your existing query as subquery and get the results
SQL FIDDLE DEMO
SELECT * from Table1 T1
JOIN
(
SELECT date, project
from table1
group by date, project
having count(*) >1
) t
on t1.date = t.date
and t1.project = t.project
This should work.
I think of the table as two sets of data and join them based on date and project and not the same student.
This way if any records exist after the join, we know that they have the same project and date but not for the same student. Group the results ... and you have what you're after.
SELECT A.student, A.date, A.project
from table a
INNER JOIN table b
on A.date=B.Date
and A.Project=B.Project
and a.student<> b.student
group by A.student, a.date, a.project
How do I generate the following reports using MYSQL?
My table 'reservations' looks like this:
id | arrival | created.
1 | 2014-3-30 | 2014-3-1
2 | 2014-3-31 | 2014-3-2
3 | 2014-3-28 | 2014-3-2
4 | 2014-3-01 | 2014-3-1
5 | 2014-3-01 | 2014-3-1
I want to generate the following two aggregation reports for the "arrival" column for the whole month as shown below:
(1)
arrival | count | total_monthly_arrivals
2014-03-01 | 2 | 5
2014-03-02 | 0 | 5
2014-03-03 | 0 | 5
...
2014-03-30 | 1 | 5
2014-03-31 | 1 | 5
(2)
January | 5
...
March | 5
...
December | 0 | 5
I want these 2 result sets. It generates date according & month according report and generate result set in these form.
I tried to use group by with count in first resultset but it doesn't retrieve for a date that does not exist. Again I wanna put month condition such that I choose month. where month = '02' or something like this. Is that possible?
My SQLFiddle should answer both parts of your question: http://sqlfiddle.com/#!2/9f130/31
This will return the arrival date with a count of how many people are coming that day and how many monthly arrivals there are
select distinct(r.arrival) as arrival_date,
count(r.arrival) as total_per_day,
sa.month_total as total_arrival_per_month
from reservations as r
,(select substr(arrival,6,2) as month,
count(substr(arrival,6,2)) as month_total
from reservations
group by month) as sa
where substr(r.arrival,6,2) = sa.month
group by arrival_date,total_arrival_per_month;
This will return the month of the year and how many people are booked for that month and how many are arriving that month. (Updated with the suggestion from agrizzo.)
select MONTHNAME(STR_TO_DATE(substr(r.arrival,6,2), '%m')) as arrival_date,
sa.month_total as total_arrival_per_month
from reservations as r
,(select substr(arrival,6,2) as month,
count(substr(arrival,6,2)) as month_total
from reservations
group by month) as sa
where substr(r.arrival,6,2) = sa.month
group by arrival_date,total_arrival_per_month;
There is however, no way for me to give you every day/month of the year without a fully qualified data set, provided by and prefilled by you. That's on you to do and provide us with.
However, you can check this thread. Get a list of dates between two dates and leverage their information with my queries to get your desired results.