I have table A
mon start end tue start end
sub009 13:00 14:00 sub004 15:00 15:30
sub004 14:00 15:00 sub005 15:30 16:00
sub005 15:00 16:00 sub009 16:00 16:30
and I am trying to get this
13:00 14:00 15:00 15:30 16:00 16:30
mon sub009 sub004 sub005
tue sub004 sub005 sub009
please I need help
Assuming you have table like this
table - monday_schedule
___________________________
Subject |startTime |endTime
___________________________
sub009 13:00 14:00
sub004 14:00 15:00
sub005 15:00 16:00
And you are plotting the subject names in the end time column, and all times are in interval of 30 min.
Then query like below will help:
select d,[14:00],[14:30],[15:00],[16:00],[16:30]
from
(select d,Subject, dayss
from
(select 'MON' as d,Subject, startTime, endTime from monday_schedule
UNION
select 'Tue' as d,Subject, startTime, endTime from tuesday_schedule
) s
UNPIVOT
( dayss for hourss in ([endTime]) )up)s
PIVOT
(
Max(Subject) for
dayss in ([14:00],[14:30],[15:00],[16:00],[16:30])
)p
Sample fiddle link : http://sqlfiddle.com/#!6/6ec0a/3
Related
I have following table from which I want to extract the time calculated. I am looking to get the Hours Spent by each employee for each day.
CREATE TABLE Attendance
(
, EmpID INT
, TimeIn datetime
, TimeOut datetime
)
The sample record against this table I have is listed below.
EmpID | AttendanceTimeIN | AttendanceTimeOut
1 2017-04-01 9:00:00 2017-04-01 10:20:00
2 2017-04-01 9:00:00 2017-04-01 12:30:00
1 2017-04-01 10:25:00 2017-04-01 17:30:00
2 2017-04-01 13:26:00 2017-04-01 14:50:00
2 2017-04-01 15:00:00 2017-04-01 18:00:00
1 2017-04-02 9:00:00 2017-04-02 11:00:00
1 2017-04-02 11:10:00 2017-04-02 12:00:00
2 2017-04-02 9:00:00 2017-04-02 12:00:00
1 2017-04-02 12:50:00 2017-04-02 18:00:00
2 2017-04-02 12:51:00 2017-04-02 18:00:00
I want to get the First TimeIn and Last TimeOut of and employee for each day to calculate how many hours a specific employee have spent in office each day.
I'm bit confused that how to use Min/Max function so I can get both employees hours for each day.
The result set I am looking for should look like this.
EmpID | AttendanceTimeIN | AttendanceTimeOut
1 2017-04-01 9:00:00 2017-04-01 17:30:00
2 2017-04-01 9:00:00 2017-04-01 18:00:00
1 2017-04-02 9:00:00 2017-04-02 18:00:00
2 2017-04-02 9:00:00 2017-04-02 18:00:00
Any help would be highly appreciated.
Thank you
If your TimeIn and TimeOut are datetime type (which they should be!), this solution works with the tests I did:
SELECT
EmpID
, MIN(TimeIn)
, MAX(TimeOut)
FROM Attendance
GROUP BY EmpID, CAST(TimeIn AS DATE)
the GROUP BY clause means that there's one row for each employee and each day, since CASTing to DATE gets rid of the time part. MIN and MAX then just inherently work.
I have two tables
tbl_TimeEntries
EmployeeID int,
StartDateTime datetime,
EndDateTime datetime
tbl_Crew_Employees
CrewID,
EmployeeID,
StartDate,
EndDate
I also have a query that produces the number of hours worked per employee per day, but I also want to include the crew the employee was on for that day.
SELECT tbl_TimeEntries.EmployeeID,
SUM(DATEDIFF(SECOND, StartDateTime, EndDateTime) / 60.0
/ 60.0) as Hours,
CAST(StartDateTime AS date) as WorkDate
FROM tbl_TimeEntries
GROUP BY tbl_TimeEntries.EmployeeID, CAST(StartDateTime AS date)
ORDER BY CAST(StartDateTime AS date)
I'm not sure how to include the CrewID in this query because the tbl_Crew_Employees uses a StartDate and EndDate (meaning the employee was on this crew from StartDate to EndDate). I would either need to expand the StartDate/EndDate range or use some sort of SQL magic of which I am unaware.
Here is a sample of the data from the tbl_Crew_Employees, tbl_TimeEntries and the current query with the desired column data added. EmployeeID 88 is represented on two different crews in the sample.
CrewID EmployeeID StartDate EndDate
13 11 2013-03-30 2013-05-12
12 88 2013-01-02 2013-04-18
12 66 2013-01-02 2013-06-30
13 88 2013-04-19 2013-04-21
11 111 2013-01-02 2013-04-28
EmployeeID StartDateTime EndDateTime
11 2013-04-18 08:00 2013-04-18 12:00
11 2013-04-18 12:30 2013-04-18 18:30
111 2013-04-18 10:00 2013-04-18 12:00
111 2013-04-18 12:30 2013-04-18 18:30
88 2013-04-18 11:00 2013-04-18 12:00
88 2013-04-18 12:30 2013-04-18 19:30
66 2013-04-18 10:00 2013-04-18 12:00
66 2013-04-18 12:30 2013-04-18 18:30
11 2013-04-20 08:00 2013-04-20 12:00
11 2013-04-20 12:30 2013-04-20 18:00
111 2013-04-20 10:00 2013-04-20 12:00
111 2013-04-20 12:30 2013-04-20 18:30
88 2013-04-20 11:00 2013-04-20 12:00
88 2013-04-20 12:30 2013-04-20 19:30
66 2013-04-20 10:00 2013-04-20 12:00
66 2013-04-20 12:30 2013-04-20 17:00
EmployeeID Hours WorkDate CrewID(desired)
11 10.00 2013-04-18 13
88 8.00 2013-04-18 12
66 8.00 2013-04-18 12
111 8.00 2013-04-18 11
11 7.50 2013-04-20 13
88 8.00 2013-04-20 13
66 6.50 2013-04-20 12
111 8.00 2013-04-20 11
Try this:
SELECT
tbl_TimeEntries.employeeid
,SUM(DATEDIFF(SECOND, StartDateTime, EndDateTime) / 60.0 / 60.0) AS HOURS
,CAST(StartDateTime AS DATE) AS WorkDate
,tbl_Crew_Employees.crewid
FROM tbl_TimeEntries
INNER JOIN tbl_Crew_Employees ON tbl_timeentries.employeeid = tbl_Crew_Employees.employeeid
AND startdatetime >= startdate
AND enddatetime <= enddate
GROUP BY tbl_TimeEntries.employeeid
,tbl_Crew_Employees.crewid
,CAST(tbl_TimeEntries.StartDateTime AS DATE)
ORDER BY WorkDate
Should be a simple join.
declare #tbl_Crew_Employees table(CrewID int, EmployeeID int, StartDate date, EndDate date)
insert into #tbl_Crew_Employees
values
(13,11,'2013-03-30','2013-05-12'),
(12,88,'2013-01-02','2013-04-18'),
(12,66,'2013-01-02','2013-06-30'),
(13,88,'2013-04-19','2013-04-21'),
(11,111,'2013-01-02','2013-04-28')
declare #tbl_TimeEntries table (EmployeeID int, StartDateTime datetime, EndDateTime datetime)
insert into #tbl_TimeEntries
values
(11,'2013-04-18 08:00','2013-04-18 12:00'),
(11,'2013-04-18 12:30','2013-04-18 18:30'),
(111,'2013-04-18 10:00','2013-04-18 12:00'),
(111,'2013-04-18 12:30','2013-04-18 18:30'),
(88,'2013-04-18 11:00','2013-04-18 12:00'),
(88,'2013-04-18 12:30','2013-04-18 19:30'),
(66,'2013-04-18 10:00','2013-04-18 12:00'),
(66,'2013-04-18 12:30','2013-04-18 18:30'),
(11,'2013-04-20 08:00','2013-04-20 12:00'),
(11,'2013-04-20 12:30','2013-04-20 18:00'),
(111,'2013-04-20 10:00','2013-04-20 12:00'),
(111,'2013-04-20 12:30','2013-04-20 18:30'),
(88,'2013-04-20 11:00','2013-04-20 12:00'),
(88,'2013-04-20 12:30','2013-04-20 19:30'),
(66,'2013-04-20 10:00','2013-04-20 12:00'),
(66,'2013-04-20 12:30','2013-04-20 17:00')
SELECT
t.EmployeeID,
c.CrewID,
SUM(DATEDIFF(SECOND, t.StartDateTime, t.EndDateTime) / 60.0
/ 60.0) ,
CAST(t.StartDateTime AS date)
FROM #tbl_TimeEntries t
INNER JOIN
#tbl_Crew_Employees c on
c.EmployeeID = t.EmployeeID
and c.StartDate <= cast(t.StartDateTime as date)
and c.EndDate >= cast(t.EndDateTime as date)
GROUP BY t.EmployeeID, CAST(t.StartDateTime AS date), c.CrewID
ORDER BY CAST(t.StartDateTime AS date)
I have a date_time column and hour_ending column,like below. How do i join them both together to derive a date_time column in 12 hour date format. my requirement is to join Table A with Table B using date_time as join key
TABLE A
DATE HOUR_ENDING
--- ----------
8/31/2016 12:00:00.000 AM 1
8/31/2016 12:00:00.000 AM 2
8/31/2016 12:00:00.000 AM 3
8/31/2016 12:00:00.000 AM 4
8/31/2016 12:00:00.000 AM 5
8/31/2016 12:00:00.000 AM 6
8/31/2016 12:00:00.000 AM 7
8/31/2016 12:00:00.000 AM 8
8/31/2016 12:00:00.000 AM 9
8/31/2016 12:00:00.000 AM 10
8/31/2016 12:00:00.000 AM 11
8/31/2016 12:00:00.000 AM 12
8/31/2016 12:00:00.000 AM 13
8/31/2016 12:00:00.000 AM 14
8/31/2016 12:00:00.000 AM 15
8/31/2016 12:00:00.000 AM 16
8/31/2016 12:00:00.000 AM 17
8/31/2016 12:00:00.000 AM 18
8/31/2016 12:00:00.000 AM 19
8/31/2016 12:00:00.000 AM 20
8/31/2016 12:00:00.000 AM 21
8/31/2016 12:00:00.000 AM 22
8/31/2016 12:00:00.000 AM 23
8/31/2016 12:00:00.000 AM 24
Table B (I need Table A to be like this)
8/31/2013 12:00:00 AM
8/31/2013 1:00:00 AM
8/31/2013 2:00:00 AM
8/31/2013 3:00:00 AM
8/31/2013 4:00:00 AM
8/31/2013 5:00:00 AM
8/31/2013 6:00:00 AM
8/31/2013 7:00:00 AM
8/31/2013 8:00:00 AM
8/31/2013 9:00:00 AM
8/31/2013 10:00:00 AM
8/31/2013 11:00:00 AM
8/31/2013 12:00:00 PM
8/31/2013 1:00:00 PM
8/31/2013 2:00:00 PM
8/31/2013 3:00:00 PM
8/31/2013 4:00:00 PM
8/31/2013 5:00:00 PM
8/31/2013 6:00:00 PM
8/31/2013 7:00:00 PM
8/31/2013 8:00:00 PM
8/31/2013 9:00:00 PM
8/31/2013 10:00:00 PM
8/31/2013 11:00:00 PM
9/1/2013 12:00:00 AM
You can use DATEADD() to adjust the dates from the A table using the hour offsets. Then, join table A to B using this adjusted timestamp.
SELECT *
FROM tableA a
INNER JOIN tableB b
ON DATEADD(HOUR, a.HOUR_ENDING, a.DATE) = b.DATE
By the way you should consider changing your table A design such that date and time are being stored together in a single column.
Help please, I have the following data in one of my MSSQL Data tables.
ID |StartDateTime |EndDateTime |OrderNo|
1 |12-08-01 08:00 |12-08-01 08:00 |6001 |
5 |12-08-01 09:00 |12-08-01 10:00 |6001 |
7 |12-08-01 10:00 |12-08-01 11:00 |6001 |
10 |12-08-01 11:00 |12-08-01 12:00 |6002 |
15 |12-08-01 12:00 |12-08-01 13:00 |6002 |
22 |12-08-01 13:00 |12-08-01 14:00 |6003 |
29 |12-08-01 14:00 |12-08-01 15:00 |6001 |
33 |12-08-01 15:00 |12-08-01 16:00 |6001 |
36 |12-08-01 16:00 |12-08-01 17:00 |6004 |
The problem is currently I have no way to tell if the OrderNo has been used multiple times. I cant tell that Order 6001 has been run twice.
I'd like to be able to add a new field to uniquely identify each run of an order from now on. But also go back over previous records and update them as well.
ID |StartDateTime |EndDateTime |OrderNo|Run|
1 |12-08-01 08:00 |12-08-01 08:00 |6001 |1 |
5 |12-08-01 09:00 |12-08-01 10:00 |6001 |1 |
7 |12-08-01 10:00 |12-08-01 11:00 |6001 |1 |
10 |12-08-01 11:00 |12-08-01 12:00 |6002 |1 |
15 |12-08-01 12:00 |12-08-01 13:00 |6002 |1 |
22 |12-08-01 13:00 |12-08-01 14:00 |6003 |1 |
29 |12-08-01 14:00 |12-08-01 15:00 |6001 |2 |
33 |12-08-01 15:00 |12-08-01 16:00 |6001 |2 |
36 |12-08-01 16:00 |12-08-01 17:00 |6004 |1 |
The idea being I can group by OrderNo and Run and will recieve the following.
OrderNo |Run |RunStart |RunEnd |
6001 | 1 |12-08-01 08:00 |12-08-01 11:00 |
6001 | 2 |12-08-01 14:00 |12-08-01 16:00 |
6002 | 1 |12-08-01 11:00 |12-08-01 13:00 |
6003 | 1 |12-08-01 13:00 |12-08-01 14:00 |
6004 | 1 |12-08-01 16:00 |12-08-01 17:00 |
I have tried multiple ways using ROW_NUMBER, CTE, cursors etc to run through the data. I have a feeling there is a simple solution but I can't figure it out.
I Hope this makes sense.
EDIT
I have changed the data tables to reference an extra complication, which I didn't include first time round. Aaron's solution provided would have worked fine. But it assumes the runs can only last for upto 2 hours (or rows). In my database these runs for n hours (or rows). Im sorry I wasn't clear first time around, and I appreciate the help given thus far.
Your edit actually makes the problem simpler to me (possibly just because I missed a simpler island approach initially).
;WITH x AS
(
SELECT OrderNo, StartDateTime, EndDateTime,
rn1 = ROW_NUMBER() OVER (ORDER BY StartDateTime),
rn = ROW_NUMBER() OVER (PARTITION BY OrderNo ORDER BY StartDateTIme)
FROM dbo.table_name -- you need to change this
),
y AS
(
SELECT OrderNo, Island = rn1 - rn,
rs = MIN(StartDateTime),
re = MAX(EndDateTime)
FROM x GROUP BY OrderNo, rn1 - rn
)
SELECT
OrderNo,
Run = ROW_NUMBER() OVER (PARTITION BY OrderNo ORDER BY rs),
RunStart = rs,
RunEnd = rs
FROM y
ORDER BY OrderNo, Run;
Leaving my original answer for posterity.
There is probably a simpler way, but this gets the answer you're after using window functions.
;WITH x AS
(
SELECT ID, StartDateTime, EndDateTime, OrderNo,
rn = ROW_NUMBER() OVER (PARTITION BY OrderNo ORDER BY StartDateTime)
FROM dbo.table_name -- you need to change this
), y AS
(
SELECT x.ID, x.StartDateTime, x.EndDateTime, x.OrderNo, x.rn,
x2ID = x2.ID, x2S = x2.StartDateTime, x2E = x2.EndDateTime,
x2O = x2.OrderNo, x2rn = x2.rn
FROM x LEFT OUTER JOIN x AS x2
ON x.OrderNo = x2.OrderNo
AND x.rn = x2.rn - 1
AND x.ID = x2.ID - 1
)
SELECT
OrderNo,
Run = ROW_NUMBER() OVER (PARTITION BY OrderNo ORDER BY StartDateTime),
RunStart = StartDateTime,
RunEnd = COALESCE(x2E, EndDateTime)
FROM y
WHERE x2ID IS NOT NULL
OR NOT EXISTS
(
SELECT 1 FROM y AS y2 WHERE y2.OrderNo = y.OrderNo AND y2.x2rn = y.rn
)
ORDER BY OrderNo, Run;
I'm querying a table which essentially a bunch of dates.
FRECDCUST DTRECDCUST DTINSPECTED DTRECDCUSTPO DTADDEDSO DTSHIPPEDSUP DTQUOTEDCUST
1/1/1900 12:00:00 AM 7/27/2010 12:00:00 AM 7/30/2010 12:00:00 AM 7/26/2010 12:00:00 AM 8/6/2010 12:00:00 AM 1/1/1900 12:00:00 AM 8/6/2010 12:00:00 AM
1/1/1900 12:00:00 AM 7/27/2010 12:00:00 AM 7/30/2010 12:00:00 AM 7/26/2010 12:00:00 AM 8/6/2010 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM
1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM
1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM
1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM 1/1/1900 12:00:00 AM
1/1/1900 12:00:00 AM 3/12/2010 12:00:00 AM 3/15/2010 12:00:00 AM 3/11/2010 12:00:00 AM 3/16/2010 12:00:00 AM 3/24/2010 12:00:00 AM 4/13/2010 12:00:00 AM
1/1/1900 12:00:00 AM 11/6/2009 12:00:00 AM 11/6/2009 12:00:00 AM 11/3/2009 12:00:00 AM 11/9/2009 12:00:00 AM 11/20/2009 12:00:00 AM 12/7/2009 12:00:00 AM
I am taking the date difference between two dates on each line. For example, the days to inspect is found like this:
SELECT (CASE
WHEN year(SYC_ext.DTRECDCUST) <> 1900
AND year(SYC_ext.DTINSPECTED) <> 1900
THEN
DATEDIFF(dd, SYC_ext.DTRECDCUST, SYC_ext.DTINSPECTED)
ELSE
NULL
END)
AS [AverageDaystoInspect]
Blah blah...
This creates a row of different DateDiff calcuations which end up looking like this:
Product Class Average Days to Inspect Average Days to Process SO Average Days to Ship to Affiliate Average Days to Quote Average Days to Receive Ammended PO
01 2 4 8 27 21
01 2 4 8 27 21
01 3 5 2 88 8
01 3 5 2 88 8
01 1 8 11 72 1
01 3 2 7 27 0
01 5 2 7 27 0
Please forgive the spacing problems.
So, each of these rows in the data set starts with a number which represents a product category in this case 01 and is followed by a series of day calculations.
I can average these values and give you an average for each category per product class. However, they want the day calculations along the left side of a table or matrix with the product classes along the top, exactly opposite of what I have here. If I pivot them in Excel, I get the following:
01 05 10
Avg Days to Inspect 5 3 5
Avg Days to Process PO 4 5 5
Avg Days to Ship 20 18 19
I hope this makes sense. Any idea how I can perform this in SSRS or t-sql?
This will do it, assuming that you can load the data from your first query into a intermediate temporary table:
DECLARE #t TABLE
(
ProductClass INT
, InspectDays INT
, ProcessDays INT
, ShipDays INT
)
INSERT INTO #t
SELECT 1
, 2
, 4
, 8
UNION ALL
SELECT 1
, 4
, 5
, 2
UNION ALL
SELECT 5
, 2
, 4
, 8
UNION ALL
SELECT 10
, 3
, 5
, 2
SELECT 'Avg Inspect'
, [01] = AVG(CASE WHEN ProductClass = 1 THEN InspectDays
END)
, [05] = AVG(CASE WHEN ProductClass = 5 THEN InspectDays
END)
, [10] = AVG(CASE WHEN ProductClass = 10 THEN InspectDays
END)
FROM #t
UNION ALL
SELECT 'Avg Process'
, [01] = AVG(CASE WHEN ProductClass = 1 THEN ProcessDays
END)
, [05] = AVG(CASE WHEN ProductClass = 5 THEN ProcessDays
END)
, [10] = AVG(CASE WHEN ProductClass = 10 THEN ProcessDays
END)
FROM #t