difference between dates excluding custom periods - mysql

Good morning,
I need a solution for counting days between specific dates. In addition I need to exclude specific dates (public holidays and weekends), which is easy and there are plenty of instructions on how to do it.
But I need to accomplish one more thing. For every person, I also have custom vacation periods and I need them to be subtracted from the previous result.
At the moment, i have two tables. One for the custom vacation periods:
+-----+----------+---------------------+---------------------+------+
| id | employee | start | end | away |
+-----+----------+---------------------+---------------------+------+
| 835 | 2.3 | 2016-12-05 00:00:00 | 2016-12-10 00:00:00 | P |
| 836 | 5.3.5.1 | 2017-01-03 00:00:00 | 2017-01-23 00:00:00 | P |
| 837 | 5.3.5.6 | 2016-12-21 00:00:00 | 2017-04-01 00:00:00 | P |
| 838 | 5.3.3.1 | 2017-01-01 00:00:00 | 2017-01-03 00:00:00 | P |
| 839 | 5.3.1.2 | 2017-01-03 00:00:00 | 2017-01-12 00:00:00 | P |
| 840 | 5.3.1.6 | 2017-01-01 00:00:00 | 2017-01-01 00:00:00 | P |
| 841 | 5.1.7 | 2017-01-09 00:00:00 | 2017-01-15 00:00:00 | P |
| 842 | 2.2 | 2017-02-16 00:00:00 | 2017-02-26 00:00:00 | P |
| 843 | 2.5 | 2017-07-31 00:00:00 | 2017-08-06 00:00:00 | P |
| 844 | 2.5 | 2017-08-21 00:00:00 | 2017-08-27 00:00:00 | P |
| 845 | 2.5 | 2017-06-26 00:00:00 | 2017-07-09 00:00:00 | P |
| 846 | 2.4 | 2017-04-04 00:00:00 | 2017-04-08 00:00:00 | P |
+-----+----------+---------------------+---------------------+------+
12 rows in set (0.00 sec)
The reason I have date and time on start and end is that the table actually has info about their working schedule also. The vacation schedule is marked by column 'away' set as 'P'.
The second table looks like this:
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | varchar(45) | YES | | NULL | |
| dayofweek | varchar(45) | YES | | NULL | |
| short | varchar(45) | YES | | NULL | |
| holiday | varchar(45) | YES | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
This table is basically a calendar with additional information about what day of week it is (i know that this can be done with dayofweek() but i need this column also), 'short' determines whether it's a shortened workday (essential when calculating hours because there are a couple of days in a year when the working day is shorter) and 'holiday' which marks public holidays.
I am trying to figure out how to calculate working days during one month (01.08.2017 - 31.08.2017) by subtracting public holidays and weekends (which I can do and is relatively easy) and also subtract custom period of vacations. The main problem is that for some people, there can be more than one period of absence during one month.
If you look at the example above, employee 2.5 has a vacation period that starts in July and ends in August and I need to subtract only the amount in that period that is in August. Employee 2.5 has another vacation in August and I need to subtract this also. In addition to that, this employee has another vacation from June to July.
The perfect outcome would be something like this:
+----------+-------+---------------+--------------+---------------+
| employee | month | working hours | working days | vacation days |
+----------+-------+---------------+--------------+---------------+
The only solution I am able to come up with is to create a new table called vacations with a column for each day and each row shows data for one employee. Or the other way around where employees are columns and rows are dates. But I would not like to start playing with this idea before i know that there isn't an easier way to do it.
Once again, I am sure that there is an easy function in mysql for this but I fail to figure it out.

To calculate working hours do this:
$to_time = strtotime("$row[2]");
$from_time = strtotime("$row[3]");
$diff = $to_time - $from_time
echo round(abs($diff) / 3600,2). " hour(s)";
Where $row[2] & $rows[3] are your start and end dates. They /3600 is for calculating hours, you can get minutes by just writing 60 instead of 3600.
As for the working days and vacations, you can set up a counter and increment it for days and decrement it for vacations using the $diff variable. Count the number of hours or days you like and then increment/decrement it the way you like.

I tidied it up a bit. I finally got what I needed.
At first I changed the calendar table:
mysql> select id,date,workday from calendar where date between '2017-06-20' and '2017-06-30';
+-----+------------+---------+
| id | date | workday |
+-----+------------+---------+
| 202 | 2017-06-20 | 1 |
| 203 | 2017-06-21 | 1 |
| 204 | 2017-06-22 | 0.625 |
| 205 | 2017-06-23 | Holiday |
| 206 | 2017-06-24 | Holiday |
| 207 | 2017-06-25 | NULL |
| 208 | 2017-06-26 | 1 |
| 209 | 2017-06-27 | 1 |
| 210 | 2017-06-28 | 1 |
| 211 | 2017-06-29 | 1 |
| 212 | 2017-06-30 | 1 |
+-----+------------+---------+
11 rows in set (0.00 sec)
1 in workday column says it's an ordinary workday, NULL means that it is not (weekend) and 0.625 is shortened workday (5/8=0,625).a shortened working day is 5 hours. This basically means if i sum the workday column and multiply it with the length of an ordinary workday, I get the normal working hours according to the law between selected period of time.
To do this, at the moment i just set up some variables, this is just a work in progress:
set #START='2016-12-01';
set #END='2016-12-31';
set #WORKDAY=8;
set #norm=(select sum(workday)*#workday from calendar where date between #start and #end);
So the variables #START and #END give me the period i am interested in. #NORM will give me the normal working hours if one is not on vacation or sick leave between #START and #END.
I added some generic data to schedule:
mysql> select id,position,start,end,away from schedule where away='P';
+-----+----------+---------------------+---------------------+------+
| id | position | start | end | away |
+-----+----------+---------------------+---------------------+------+
| 835 | 2.3 | 2016-12-05 00:00:00 | 2016-12-10 00:00:00 | P |
| 836 | 5.3.5.1 | 2017-01-03 00:00:00 | 2017-01-23 00:00:00 | P |
| 837 | 5.3.5.6 | 2016-12-21 00:00:00 | 2017-04-01 00:00:00 | P |
| 838 | 5.3.3.1 | 2017-01-01 00:00:00 | 2017-01-03 00:00:00 | P |
| 839 | 5.3.1.2 | 2017-01-03 00:00:00 | 2017-01-12 00:00:00 | P |
| 840 | 5.3.1.6 | 2017-01-01 00:00:00 | 2017-01-01 00:00:00 | P |
| 841 | 5.1.7 | 2017-01-09 00:00:00 | 2017-01-15 00:00:00 | P |
| 842 | 2.2 | 2017-02-16 00:00:00 | 2017-02-26 00:00:00 | P |
| 843 | 2.5 | 2017-07-31 00:00:00 | 2017-08-06 00:00:00 | P |
| 844 | 2.5 | 2017-08-21 00:00:00 | 2017-08-27 00:00:00 | P |
| 845 | 2.5 | 2017-06-26 00:00:00 | 2017-07-09 00:00:00 | P |
| 846 | 2.4 | 2017-04-04 00:00:00 | 2017-04-08 00:00:00 | P |
| 847 | 2.3 | 2017-07-31 00:00:00 | 2017-08-06 00:00:00 | P |
| 848 | 2.3 | 2017-08-21 00:00:00 | 2017-08-27 00:00:00 | P |
| 849 | 2.3 | 2017-06-26 00:00:00 | 2017-07-09 00:00:00 | P |
| 850 | 2.5 | 2017-08-29 00:00:00 | 2017-09-15 00:00:00 | P |
| 851 | 2.3 | 2017-08-29 00:00:00 | 2017-09-15 00:00:00 | P |
| 852 | 2.1 | 2016-11-15 00:00:00 | 2016-12-20 00:00:00 | P |
| 853 | 2.2 | 2016-11-10 00:00:00 | 2017-01-15 00:00:00 | P |
+-----+----------+---------------------+---------------------+------+
19 rows in set (0.00 sec)
And to get the info about each employees specific working I use following select:
SELECT position,#NORM AS normhrs,#NORM - (SUM(vac_workday))*#WORKDAY AS wrkhrs
FROM
(
SELECT position,holiday_start,holiday_end,
(SELECT SUM(workday) FROM calendar WHERE date BETWEEN holiday_start AND holiday_end) AS vac_workday
FROM
(
SELECT position,
DATE_FORMAT(CASE WHEN start<=#START THEN #START ELSE start END,'%Y-%m-%d') AS 'holiday_start',
DATE_FORMAT(CASE WHEN end>=#END THEN #END ELSE end END,'%Y-%m-%d') AS 'holiday_end'
FROM schedule WHERE away IS NOT NULL AND DATE_FORMAT(CASE WHEN start<=#START AND end>=#START THEN #START
WHEN start>=#START AND start<=#END THEN start
ELSE NULL end,'%Y-%m')=DATE_FORMAT(#START,'%Y-%m')
)
AS outertable
)
AS outertable2 GROUP BY position;
which gives me the output. there are only people who have vacations from #START to #END. If the person is not in the output, norm hours apply:
+----------+---------+--------+
| position | normhrs | wrkhrs |
+----------+---------+--------+
| 2.1 | 165 | 53 |
| 2.2 | 165 | 0 |
| 2.3 | 165 | 133 |
| 5.3.5.6 | 165 | 120 |
+----------+---------+--------+
4 rows in set, 6 warnings (0.00 sec)
This is the output i was looking for. i still need to come up with SELECT to sum up the actual working hours but it is easy enough not to put it in here.
Sorry, i know i'm over explaining some stuff but i being total noob, have found similar, rather superthorough answers, very helpful.

Related

SQL Query: find lots that belong to current auction

I have a table auctions and a table lots:
mysql> select id, auction_name, auction_startdate, auction_planned_closedate from auctions;
+----+--------------+---------------------+---------------------------+
| id | auction_name | auction_startdate | auction_planned_closedate |
+----+--------------+---------------------+---------------------------+
| 1 | Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 |
| 2 | Auction 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 |
| 3 | Auction 3 | 2016-07-01 00:00:00 | 2016-08-30 00:00:00 |
| 4 | Auction 4 | 2016-09-01 00:00:00 | 2016-10-30 00:00:00 |
+----+--------------+---------------------+---------------------------+
mysql> select id, auction_id, lot_name from lots;
+----+------------+----------+
| id | auction_id | lot_name |
+----+------------+----------+
| 1 | 1 | Lot 1 |
| 2 | 1 | Lot 2 |
| 3 | 1 | Lot 3 |
| 4 | 1 | Lot 4 |
| 5 | 1 | Lot 5 |
| 6 | 1 | Lot 6 |
| 7 | 1 | Lot 7 |
| 8 | 2 | Lot 8 |
| 9 | 2 | Lot 9 |
| 10 | 2 | Lot 10 |
| 11 | 3 | Lot 11 |
| 12 | 3 | Lot 12 |
| 13 | 3 | Lot 13 |
| 14 | 3 | Lot 14 |
| 15 | 4 | Lot 15 |
| 16 | 4 | Lot 16 |
+----+------------+----------+
I want to display only the lots for current auctions (which are auctions 1 and 2 in the example), in other words for which the current time is between the 'auction_startdate' and 'auction_planned_closedate'.
So here is what I want to achieve:
+--------------+---------------------+---------------------------+---------+
| auction_name | auction_startdate | auction_planned_closedate | lots_id |
+--------------+---------------------+---------------------------+---------+
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 1 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 2 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 3 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 4 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 5 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 6 |
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 | 7 |
| Auction 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 | 8 |
| Auction 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 | 9 |
| Auction 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 | 10 |
+--------------+---------------------+---------------------------+---------+
The following query gets me the current auctions:
mysql> select auction_name, auction_startdate, auction_planned_closedate from auctions where now() >= auction_startdate and now() <= auction_planned_closedate;
+--------------+---------------------+---------------------------+
| auction_name | auction_startdate | auction_planned_closedate |
+--------------+---------------------+---------------------------+
| Auction 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 |
| Auction 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 |
+--------------+---------------------+---------------------------+
and then I do an inner join with the 'lots' table:
select auction_name, auction_startdate, auction_planned_closedate, lots.id
from auctions
where now() >= auction_startdate
and now() <= auction_planned_closedate
inner join lots on auctions.id = lots.auction_id;
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'inner join lots on auctions.id=lots.auction_id' at
line 1
I'm getting a syntax error which I'm staring blind at for a while.
Wrong order, put the WHERE clause after the JOIN:
select auction_name, auction_startdate, auction_planned_closedate, lots.id
from auctions
inner join lots on auctions.id = lots.auction_id
where now() >= auction_startdate
and now() <= auction_planned_closedate
Your join is in the wrong order:
select a.auction_name, a.auction_startdate, a.auction_planned_closedate, l.id
from auctions a inner join
lots l
on a.id = l.auction_id
where now() >= a.auction_startdate and now() <= a.auction_planned_closedate ;
Notes:
where goes after the from clause. join is not a separate clause; it is an operator in the from clause.
Table aliases make a query easier to write and to read.
Qualify all the column names. This makes it clear where the columns are coming from.

MySQL: MIN and Group By: Get the first timestamp of 12x # events for each person's day

What I want to do is to get the smallest scheduled time for each user in a given day. For the examples below I've highlighted just that day's events, which I will filter on my end simply by adding
AND DATE_ADD(scheduled, INTERVAL -$timezone_offset MINUTE)>='$given_day 00:00:00'
AND DATE_ADD(scheduled, INTERVAL -$timezone_offset MINUTE)< '$next_day 00:00:00'
For a simplified example I've got two tables:
checkpoints
+------+---------+----------+---------------------+
| id | type_id | event_id | scheduled |
+------+---------+----------+---------------------+
| 1111 | 9 | 2222 | 2015-06-05 12:00:00 |
| 1150 | 1 | 2222 | 2015-06-05 10:00:00 |
| 1200 | 11 | 3333 | 2015-06-05 23:00:00 |
| 1305 | 1 | 4444 | 2015-06-05 15:00:00 |
| 1400 | 2 | 4444 | 2015-06-05 05:00:00 |
| 1405 | 3 | 4444 | 2015-06-05 19:00:00 |
| 1500 | 1 | 5555 | 2015-06-05 17:00:00 |
| 1505 | 9 | 5555 | 2015-06-05 18:00:00 |
+------+---------+----------+---------------------+
events
+------+---------+---------------------+
| id | user_id | start |
+------+---------+---------------------+
| 2222 | 3 | 2015-06-05 11:00:00 |
| 3333 | 5 | 2015-06-05 23:00:00 |
| 4444 | 2 | 2015-06-05 07:00:00 |
| 5555 | 5 | 2015-06-05 19:00:00 |
+------+---------+---------------------+
I want to query such that I get the following:
+------+---------+---------------------+---------------------+
| id | user_id | start | scheduled |
+------+---------+---------------------+---------------------+
| 1150 | 3 | 2015-06-05 11:00:00 | 2015-06-05 10:00:00 |
| 1500 | 5 | 2015-06-05 19:00:00 | 2015-06-05 17:00:00 |
| 1400 | 2 | 2015-06-05 07:00:00 | 2015-06-05 05:00:00 |
+------+---------+---------------------+---------------------+
That is: the first scheduled time of any given driver's day.
The query I thought would work is:
SELECT
checkpoints.id AS id,
user_id,
start,
MIN(scheduled) AS scheduled
FROM checkpoints
LEFT JOIN events ON event_id=events.id
WHERE DATE_ADD(scheduled, INTERVAL -240 MINUTE)>='2015-06-05 00:00:00'
AND DATE_ADD(scheduled, INTERVAL -240 MINUTE)<'2015-06-06 00:00:00'
AND user_id IS NOT NULL
GROUP BY user_id, DATE(DATE_ADD(scheduled, INTERVAL -240 MINUTE));
The problem is that I'm getting the wrong checkpoint id and start time, even though the user_id and earliest are correct. To illustrate the problem, I see a result like:
+------+---------+---------------------+---------------------+
| id | user_id | start | scheduled |
+------+---------+---------------------+---------------------+
| 1200 | 5 | 2015-06-05 23:00:00 | 2015-06-05 17:00:00 |
+------+---------+---------------------+---------------------+
What am I doing wrong?
Your query would be illegal for most of SQL implementations. MySQL allows to SELECT columns that are neither aggregated nor included in GROUP BY clause.
However, the server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate

Appointment system mysql query

I need to write a query to select all free slots from appointment table but have problem writing such complex query. Maybe someone could help me I will try to explain what I need to get.
I have table structure:
+---------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| patient_id | int(11) | YES | MUL | NULL | |
| start_time | datetime | NO | | NULL | |
| end_time | datetime | NO | | NULL | |
+---------------+----------+------+-----+---------+----------------+
The problem is that I need to get free slots. For e.g. The works starts at 8:00 AM and ends at 8:00PM and this goes from Monday to Saturday. From last appointment free space should like 1 year in advance. So here is example response that I expect:
+---------------------+---------------------+------------------+
| Free Time Start | Free Time End | Free Time Length |
+---------------------+---------------------+------------------+
| 2014-09-15 08:00:00 | 2014-09-15 08:30:00 | 30 |
| 2014-09-15 09:30:00 | 2014-09-15 12:00:00 | 150 |
| 2014-09-15 15:00:00 | 2014-09-15 20:00:00 | 300 |
| 2014-09-16 09:00:00 | 2014-09-16 11:30:00 | 150 |
| 2014-09-16 13:00:00 | 2014-09-16 17:00:00 | 240 |
| 2014-09-16 18:00:00 | 2015-09-16 18:00:00 | 525600 |
+---------------------+---------------------+------------------+
The sample data for results above:
+----+------------+---------------------+---------------------+
| id | patient_id | start_time | end_time |
+----+------------+---------------------+---------------------+
| 1 | 1 | 2014-09-15 08:30:00 | 2014-09-15 09:30:00 |
| 2 | 1 | 2014-09-15 12:00:00 | 2014-09-15 15:00:00 |
| 3 | 1 | 2014-09-16 08:00:00 | 2014-09-16 09:00:00 |
| 4 | 1 | 2014-09-16 11:30:00 | 2014-09-16 13:00:00 |
| 5 | 1 | 2014-09-16 17:00:00 | 2014-09-16 18:00:00 |
+----+------------+---------------------+---------------------+
So in plain query should:
Get free space 08:00:00 <= x <= 20:00:00 and through monday to saturday (Other days, hours should be skipped)
After last appointment free time range should be 1 year in advance
Sorry if similar questions exists I could not reuse that solutions for hour/day offsets and 1 year in advance... I tried to do this in PHP but it tooks a really long time...

MySQL filter by GROUP BY result

I don't know if this is something I can achieve effectively with sub queries, or how to even build a query for this. I have to extract some knowledge about people no longer using our system. Imagine we have 3 users with user id 1024, 1234, and 5678; and User 1024 and 1234 are using theme A, and 5678 is using theme B:
$ SELECT * FROM user; | $ SELECT * FROM user_theme;
+------+------+ | +------+-------+
| id | name | | | user | theme |
+------+------+ | +------+-------+
| 1024 | John | | | 1024 | A |
| 1234 | Jane | | | 1234 | A |
| 5678 | Jeff | | | 5678 | B |
+------+------+ | +------+-------+
The usage tracking table appears as this:
$ SELECT * FROM user_usage;
+----+------+---------------------+------+
| id | user | date | uses |
+----+------+---------------------+------+
| 1 | 1234 | 2014-08-02 00:00:00 | 5 |
| 2 | 1234 | 2014-08-03 00:00:00 | 5 |
| 3 | 1234 | 2014-08-04 00:00:00 | 3 |
| 4 | 1234 | 2014-08-05 00:00:00 | 6 |
| 5 | 1024 | 2014-08-02 00:00:00 | 8 |
| 6 | 1024 | 2014-08-03 00:00:00 | 7 |
| 7 | 1024 | 2014-08-04 00:00:00 | 4 |
| 8 | 1024 | 2014-08-05 00:00:00 | 6 |
| 9 | 1024 | 2014-09-02 00:00:00 | 1 |
| 10 | 1024 | 2014-09-03 00:00:00 | 2 |
| 11 | 1024 | 2014-09-04 00:00:00 | 3 |
| 12 | 1024 | 2014-09-05 00:00:00 | 4 |
| 13 | 5678 | 2014-08-02 00:00:00 | 8 |
| 14 | 5678 | 2014-08-03 00:00:00 | 7 |
| 15 | 5678 | 2014-08-04 00:00:00 | 4 |
| 16 | 5678 | 2014-08-05 00:00:00 | 6 |
| 17 | 5678 | 2014-09-02 00:00:00 | 1 |
| 18 | 5678 | 2014-09-03 00:00:00 | 2 |
| 19 | 5678 | 2014-09-04 00:00:00 | 3 |
| 20 | 5678 | 2014-09-05 00:00:00 | 4 |
+----+------+---------------------+------+
I want to find out the break down to see how many usage have dropped from our system in 2014-09 (aka: have usage data in 2014-08, but no longer in 2014-09), grouped by the theme. So I want to write something like:
SELECT
user_theme.theme,
SUM(user_usage.users) 'uses lost'
FROM
user_theme
LEFT JOIN user_usage
ON user_theme.user = user_usage.user
WHERE
...
GROUP BY
user_theme.theme
# HAVING ...?
And get result such as:
+-------+-----------+
| theme | uses lost |
+-------+-----------+
| A | 19 |
| B | 0 |
+-------+-----------+
Where the 19 comes from SUM(uses) for WHERE user = 1234 AND YEAR(date) = 2014 AND MONTH(date) = 8.
I don't know I care about the SUM(uses) from user = 1234 in advance, because I only know I need to include user 1234 in the SUM(uses)'s WHERE clause because SUM(uses) for WHERE user = 1234 AND YEAR(date) = 2014 AND MONTH(date) = 9 is 0.
There's actually a lot of users, and a handful of themes (around 20K users, and about 10 themes), so ideally, I think I'd like to avoid doing the filtering in code as opposed to directly in the database. Is there a way to do this effectively in MySQL using raw SQL queries?
Here is query which compares current month with previous one:
set #current_month = now();
set #previous_month = date_sub(#current_month, interval 1 month);
set #current_month = concat(year(#current_month), month(#current_month));
set #previous_month = concat(year(#previous_month), month(#previous_month));
select a.`theme`, sum(ifnull(b.uses_lost,0)) as uses_lost
from
`user_theme` as a
left outer join
(
select `user`, sum(uses) as uses_lost
from `user_usage`
where concat(year(`date`), month(`date`)) = #previous_month
and `user` not in (
select `user`
from `user_usage`
where concat(year(`date`), month(`date`)) = #current_month)
group by `user`
) as b
on (a.`user`=b.`user`)
group by a.`theme`;
fiddle for play
main idea is to find all users who used system during last month and has no rows during current month

SQL server pivot table for time keeping

I have a time keeping table that records the following data:
+----------------+-------------------------+-------+
| TK_EMPLOYEE_ID | TK_DATETIME | TK_ID |
+----------------+-------------------------+-------+
| 101 | 2013-09-30 08:01:54.000 | 1 |
| 101 | 2013-09-30 12:02:16.000 | 2 |
| 101 | 2013-09-30 12:30:12.000 | 3 |
| 101 | 2013-09-30 16:31:02.000 | 4 |
| 101 | 2013-10-01 08:33:59.000 | 5 |
| 101 | 2013-10-01 12:05:59.000 | 6 |
| 101 | 2013-10-01 12:30:29.000 | 7 |
| 101 | 2013-10-01 16:40:48.000 | 8 |
| 102 | 2013-10-01 08:00:48.000 | 9 |
| 102 | 2013-10-01 12:00:48.000 | 10|
+----------------+-------------------------+-------+
The clock entries are taken so that the odd scans are "CLOCK IN" and the even are "CLOCK OUT". So in the table above we can see that the employee clocked in at 8:01am, clocked out at 12:02; clocked back in from lunch at 12:30 and left work and 16:31.
How could I format display this in a SQL pivot table to display something like the following detailing entries for each day of the week?
EMPID | Mon | Tue | Wed
101 | 8:01 - 12:02 (4:01) | 08:33 - 12:05 (03:32) | etc
| 12:30- 16:31 (4:01) | 12:30 - 16:40 (04:10 |
102 | 8:00- 12:00 (4:00)
The time difference between the two times is shown in brackets.
I plan on using SSRS to display the results.