tags:

views:

46

answers:

3

Hi,

I'm currently trying to write a query that will return all users that have not logged time for a given date in our timesheet system. We currently have 2 tables, timesheets and users. I am trying to make a query that will return a list of users that do not have an entry in the timesheets table for a date range. There is only one record in the timesheets table per-day, this should be simple but I can't figure out how to approach this for the life of me.

Any help would be appreciated :).

+-----------------------+------------------+------+-----+---------+----------------+
| Field                 | Type             | Null | Key | Default | Extra          |
+-----------------------+------------------+------+-----+---------+----------------+
| timesheetID           | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| timesheetForUser      | int(11) unsigned | NO   |     |         |                |
| timesheetForDate      | date             | NO   |     |         |                |
| timesheetForCheckIn   | int(11)          | YES  |     | NULL    |                |
| timesheetNotes        | text             | YES  |     | NULL    |                |
| timesheetIsFilled     | tinyint(1)       | NO   |     |         |                |
| timesheetNoFillReason | int(11) unsigned | NO   |     |         |                |
| timesheetCreatedOn    | datetime         | NO   |     |         |                |
| timesheetCreatedBy    | int(11) unsigned | NO   |     |         |                |
| timesheetUpdatedOn    | datetime         | YES  |     | NULL    |                |
| timesheetUpdatedBy    | int(11) unsigned | YES  |     | NULL    |                |
+-----------------------+------------------+------+-----+---------+----------------+
+--------------------------------+---------------+------+-----+---------+----------------+
| Field                          | Type          | Null | Key | Default | Extra          |
+--------------------------------+---------------+------+-----+---------+----------------+
| userID                         | int(11)       | NO   | PRI | NULL    | auto_increment |
| userAccount                    | int(11)       | YES  |     | NULL    |                |
| userOrganization               | int(11)       | YES  |     | NULL    |                |
| userIsEmployee                 | tinyint(4)    | YES  |     | 0       |                |
| userEmployeeSince              | date          | YES  |     | NULL    |                |
| userName                       | varchar(255)  | YES  |     | NULL    |                |
| userTitle                      | varchar(255)  | YES  |     | NULL    |                |
| userEmail                      | varchar(255)  | YES  |     | NULL    |                |
| userLogin                      | varchar(50)   | YES  |     | NULL    |                |
| userPassword                   | varchar(255)  | YES  |     | NULL    |                |
| userSendInvitation             | tinyint(4)    | YES  |     | NULL    |                |
| userAddress1                   | varchar(255)  | YES  |     | NULL    |                |
| userAddress2                   | varchar(255)  | YES  |     | NULL    |                |
| userCity                       | varchar(255)  | YES  |     | NULL    |                |
| userCountry                    | char(2)       | YES  |     | NULL    |                |
| userState                      | varchar(6)    | YES  |     | NULL    |                |
| userStateOther                 | varchar(255)  | YES  |     | NULL    |                |
| userZip                        | varchar(20)   | YES  |     | NULL    |                |
| userPhone                      | varchar(50)   | YES  |     | NULL    |                |
| user_easypaycode               | varchar(6)    | YES  |     | NULL    |                |
| userFax                        | varchar(50)   | YES  |     | NULL    |                |
| userCell                       | varchar(50)   | YES  |     | NULL    |                |
| userTimezone                   | int(11)       | YES  |     | NULL    |                |
| userNotes                      | text          | YES  |     | NULL    |                |
| userActive                     | tinyint(4)    | NO   |     | 0       |                |
| userDisplayPictureType         | tinyint(4)    | YES  |     | NULL    |                |
| userDisplayPicture             | varchar(255)  | YES  |     | NULL    |                |
| userThumbnailPicture           | varchar(255)  | YES  |     | NULL    |                |
| userCanWriteMessages           | tinyint(4)    | NO   |     | 0       |                |
| userCanWriteComments           | tinyint(4)    | NO   |     | 0       |                |
| userCanUploadFiles             | tinyint(4)    | NO   |     | 0       |                |
| userCanCreateEvents            | tinyint(4)    | NO   |     | 0       |                |
| userCanCreateTickets           | tinyint(4)    | NO   |     | 0       |                |
| userCanManageProjects          | tinyint(4)    | NO   |     | 0       |                |
| userCanManageUsers             | tinyint(4)    | NO   |     | 0       |                |
| userCanManageOrganizations     | tinyint(4)    | NO   |     | 0       |                |
| userCanManageUserGroups        | tinyint(4)    | NO   |     | 0       |                |
| userCanManageMessageCategories | tinyint(4)    | NO   |     | 0       |                |
| userCanManageSetupOptions      | tinyint(4)    | NO   |     | 0       |                |
| userCanManageAllUsersItems     | tinyint(4)    | NO   |     | 0       |                |
| userCanEnterTimesheets         | tinyint(4)    | NO   |     |         |                |
| userCanManageTimesheets        | tinyint(4)    | NO   |     |         |                |
| userCanUseTimeclock            | tinyint(4)    | YES  |     | NULL    |                |
| userCanOnlyUseTimeclock        | tinyint(4)    | YES  |     | NULL    |                |
| userLastLogin                  | datetime      | NO   |     |         |                |
| userPWResetText                | varchar(255)  | YES  |     | NULL    |                |
| userDeleted                    | tinyint(4)    | NO   |     | 0       |                |
| userDeletedBy                  | int(11)       | YES  |     | NULL    |                |
| userDeletedOn                  | datetime      | YES  |     | NULL    |                |
| userMinHoursPerDay             | decimal(10,1) | YES  |     | NULL    |                |
+--------------------------------+---------------+------+-----+---------+----------------+

In addition there is no record created in timesheets if there is no time logged for a day.

+3  A: 

The first query fetches all the users that have no registrations between @start and @end:

SELECT users.userName
FROM users
LEFT JOIN timesheets
ON timesheets.timesheetForUser = users.userID
AND timesheets.timesheetForDate BETWEEN @start AND @end
WHERE timesheets.timesheetForUser IS NULL

This query fetches all users that are missing any days and which days they are missing (as you requested in an comment to your question):

SELECT dates.timesheetForDate, users.userName
FROM (SELECT DISTINCT timesheetForDate FROM timesheets) AS dates
CROSS JOIN users
LEFT JOIN timesheets
    ON timesheets.timesheetForUser = users.userID
    AND dates.timesheetForDate = timesheets.timesheetForDate
WHERE timesheets.timesheetForUser IS NULL

Test bed:

CREATE TABLE timesheets (timesheetForUser int, timesheetForDate datetime);
INSERT INTO timesheets (timesheetForUser, timesheetForDate) VALUES
(1, '2010-01-01'),
(2, '2010-01-01'),
(3, '2010-01-01'),
(1, '2010-01-02'),
(3, '2010-01-02'),
(2, '2010-01-03'),
(2, '2010-01-04'),
(3, '2010-01-04');

CREATE TABLE users (userId int, userName nvarchar(100));
INSERT INTO users (userId, userName) VALUES
(1, 'Foo'),
(2, 'Bar'),
(3, 'Baz');

Output from second query using test bed:

'2010-01-02 00:00:00', 'Bar'
'2010-01-03 00:00:00', 'Foo'
'2010-01-03 00:00:00', 'Baz'
'2010-01-04 00:00:00', 'Foo'

If you want you can also create the second query as a view and query it like this:

SELECT * FROM ViewMissingRegistrations
WHERE timesheetForDate BETWEEN @start AND @end
Mark Byers
this does not work as there is no record made in timesheets for days which no time is logged. Unless I really misunderstand SQL which is possible too :S
Jonathan
@Jonathan, it's using a LEFT JOIN which means that it will return NULL for columns in the right hand table. it should work fine, unless I've misunderstood your question.
AJ
@Johnathan: I've updated my query to use your column names. I've also added a second query that answers your updated question that you put as a comment to your question. The second query also includes a testbed so that you can see it works here.
Mark Byers
A: 

You could try

SELECT  u.*
FROM    Users u LEFT JOIN
        timesheets t ON u.userid = t.userid
WHERE   t.Date BETWEEN '01 Jan 2009' AND '31 Jan 2009'
AND     t.userID IS NULL
astander
I think this won't work. I think that if t.userId is null then t.DATE will be null too, so it seems to me that your WHERE clause will always be false. Anyway it returns no rows for the testbed I posted above (after changing the column names accordingly).
Mark Byers
+2  A: 
SELECT * FROM Users U
   WHERE U.UserNo NOT IN (
     SELECT timesheetForUser FROM timesheets 
       WHERE timesheetForDate BETWEEN ??? AND ???
   )
Carlos Gutiérrez
thx, that was exactly what I needed. I somehow managed to forget that mysql can do subqueries :S.
Jonathan