I have five tables:
Employees(EmpId, FirstName, LastName, DeptId,…)
Attendance(LogId, PunchIn, PunchOut,...)
Leave(RequestId, StartDate, endDate, LeaveType,...)
Holiday(HolidayId, Descriptions, StartDate, EndDate,....)
Business Travel(Request_Id, RequestDate, StartDate, EndDate,....)
I am trying to generate a monthly/Annual time-sheet report, time-sheet must represent an employee (or group of employees) status at the corresponding date like: on duty, later arrived, leave vacation, sick leave etc.
I create the following function
Create Function dbo.fn_GetEmployeeStatus(#LogDate Date, #BadgeNo int)
Returns char(3)
As
begin
Declare #status char(3) = null;
Declare #punchin DateTime;
Declare #punchout DateTime;
Declare #ShiftId tinyint;
Declare #LateEarly smallint;
Declare #id int = null;
Set #status = null;
Select #ShiftId = Shift_Id From Staff
Where Badge_No = Badge_No;
Select #id = Max(Holiday_Id) From Holiday
Where #LogDate Between StartDate And EndDate
if(#id is not null)
Set #status = 'HOL' --Holiday
else Set #status = null;
if(#status is null)
begin
Set #id = null;
Select #id = Max(Request_Id) From BusinessTravel
Where #LogDate Between Start_Date And End_Date
And Badge_No = #BadgeNo
if(#id is not null)
Set #status = 'BST' --Business Travel
else Set #status = null;
end
if(#status is null)
begin
Set #id = null;
Select #id = Max(LeaveCategory_Id) From Leaves
Where #LogDate Between Start_Date And End_Date
And Badge_No = #BadgeNo
if(#id is not null)
begin
Set #status = Case #id
When 1 Then 'ANV' --Annual Leave
When 2 Then 'SIC' --Sick leave
When 3 Then 'SLV' --Study leave
When 4 Then 'ELV' --Emergency leave
When 5 Then 'ULV' --Unpaid leave
When 6 Then 'HLV' --Haj Leave
When 7 Then 'MLV' --Marriage leave
When 8 Then 'DLV' --Death of a relative
When 9 Then 'PLV' --Paternity leave
When 7 Then 'MLV' --Materinty Leave
else 'UNK' end; --Unknown
end else Set #status = null;
end
if(#status is null)
begin
Select #punchin = Min(Log_Date), #punchout = Max(Log_Date) From AttendanceLog
Where Cast(Log_Date as Date) = #LogDate
And Badge_No = #BadgeNo
if(#punchin is not null)
begin
Select #LateEarly = dbo.fun_GetEarlyLateAmt(#punchin, 1, #ShiftId)
if(#LateEarly > 20)
begin
Select #LateEarly = dbo.fun_GetEarlyLateAmt(#punchout, 0, #ShiftId)
if(#LateEarly > 10)
Set #status = 'L&E'; --Late Arrive & Early left
else Set #status = 'LTE'; --Late Arrive
end else Set #status = 'ODU'; --On Duty
end --else Set #status = null;
end
if(#status is null)
begin
if ((DatePart(dw, #LogDate) + ##DateFirst) % 7) in(0, 6)
Set #status = 'WKE'; --Weekend
Set #status = 'ABS';
end --else Set #status = 'ABS';
Return #status;
end
--But the following failed
Declare
#BadgeNo int = 2523,
#Year int = 2019
;With data as (
Select DateName(month, InTime) Mon, LogInDay = DATEPART(DAY, DATEADD(HOUR, -6, InTime))
,LogYear = DATEPART(YEAR, InTime), LogMonth = DATEPART(MONTH, InTime),
dbo.fn_GetEmployeeStatus_2(InTime, Badge_No) eStatus From v_EmpAttendanceStatus--v_AttendanceLog
Where DATEPART(YEAR, InTime) = #Year
And Badge_No = #BadgeNo)
Select Mon, LogYear, LogMonth, IsNull([1], 0)[1], IsNull([2], 0)[2], IsNull([3], 0)[3], IsNull([4], 0)[4], IsNull([5], 0)[5], IsNull([6], 0)[6], IsNull([7], 0)[7], IsNull([8], 0)[8], IsNull([9], 0)[9], IsNull([10], 0)[10], IsNull([11], 0)[11], IsNull([12], 0)[12], IsNull([13], 0)[13], IsNull([14], 0)[14], IsNull([15], 0)[15], IsNull([16], 0)[16], IsNull([17], 0)[17], IsNull([18], 0)[18], IsNull([19], 0)[19], IsNull([20], 0)[20], IsNull([21], 0)[21], IsNull([22], 0)[22], IsNull([23], 0)[23], IsNull([24], 0)[24], IsNull([25], 0)[25], IsNull([26], 0)[26], IsNull([27], 0)[27], IsNull([28], 0)[28], IsNull([29], 0)[29], IsNull([30], 0)[30], IsNull([31], 0)[31]
From data
Pivot (
Max(eStatus)
For LogInDay In
([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31])
) as piv
Order By LogMonth
Above cte result not shown holidays and leave vacation. I need the report like bellow image.
--Sample Data
1- Employee Table:
#Badge_No FirstName LastName DeptId#
2523 Name1 Last1 1001
2524 Name2 Last2 1001
2525 Name3 Last3 1006
-------------------------------------------------------------------
2- Holiday Table:
ID Sescriprions StartDate EndDate
1 Holidy1 '02 Jun 2019' '08 Jun 2019'
1 Holidy2 '23 Sep 2019' '24 Sep 2019'
---------------------------------------------------------------------
3- Leave Table:
#Request_Id Badge_No StartDate EndDate LeaveCategory#
1 2525 '15 Dec 2018' '22 Jan 2019' 2 --Sick leave
...
101 2524 '01 Jan 209' '03 Jan 209' 2 --Sick Leave
2061 2523 '09 Jun 2019' '04 Jul 2019' 1 --Annual Leave
..
2125 2523 '22 Jul 2019' '22 Jul 2019' 5 --Unpaid leave
--------------------------------------------------------------
4- Attendance Table:
#Badge_No Punch-In Punch-Out Shift_Id#
2523 '01 Jan 2019 07:04' '01 Jan 2019 16:01' 1
2524 '01 Jan 2019 07:45 '01 Jan 2019 15:56' 1
.......
2523 '28 Jan 2019 06:50' '28 Jan 2019 16:03' 1
2524 '28 Jan 2019 07:02' '28 Jan 2019 16:00' 1
2525 '28 Jan 2019 07:42' '28 Jan 2019 16:00' 1
2523 '29 Jan 2019 07:30' '29 Jan 2019 15:59' 1
2524 '29 Jan 2019 06:58' '29 Jan 2019 16:01' 1
2523 '30 Jan 2019 07:13' '30 Jan 2019 07:18' 1
2525 '30 Jan 2019 09:18' '30 Jan 2019 07:18' 1
2524 '30 Jan 2019 08:11' '30 Jan 2019 16:00' 1
2525 '30 Jan 2019 10:26' '30 Jan 2019 16:00' 1
2523 '31 Jan 2019 11:27' '31 Jan 2019 15:54' 1
2524 '31 Jan 2019 07:02' '31 Jan 2019 15:51' 1
.......
2523 '25 Jul 2019 08:17' '25 Jul 2019 17:23' 1
--------------------------------------------------------------
5- BusinessTravel Table:
#Badge_No StartDate EndDate#
2523 '07 Jan 2019' '09 Jan 2019'
2525 '03 Mar 2019' '07 Mar 2019'
Related
I am working on a SQL query where I have to select only one value of given time interval in seconds.
Suppose I give time interval=5, then the value should come after every 5 seconds. If I give time interval=60, then the value should come after every 60 seconds i.e. after every minute. If I give time interval=300, then the value should come after every 300 seconds i.e. after every 5 minutes and so on.
For this I used the following query
DECLARE #FROMDATETIME DATE = '2016-09-21 14:00',
#TODATETIME DATE = '2020-09-21 14:00',
#INTERVAL NVARCHAR(50) = '300'
DECLARE #intv INT = ((CONVERT(INT, #INTERVAL)) / 60)
SELECT
CONVERT(NVARCHAR(20), DATEANDTIME, 113) DATETIME,
ALARM, F870 'COLD JUICE PRE [PSI]',
F872 'COLD WATER PRE [PSI]', F82 'FILLER TEMP [DEGC]',
F810 'FLOW [LTR/MIN]', F869 'HOT JUICE PRE[PSI]',
F874 'HOT WATER PRE[PSI]', F867 'HOT WATER TEMP[DEGC]',
F84 'JUICE TEMP AFTER HOLD TUBE[DEGC]', F822 'PD FOR COLD PHE[PSI]',
F821 'PD FOR HOT PHE[PSI]', F8X 'PHE INLET TEMP[DEGC]',
B1 'MACHINE 1 STATUS', B2 'MACHINE 2 STATUS'
FROM
(SELECT
DATEANDTIME,
NULL ALARM, F870 F870, F872 F872, F82 F82, F810 F810, F869 F869,
F874 F874, F867 F867, F84 F84, F822 F822, F821 F821, F8X F8X,
CASE
WHEN B1 = 1 THEN 'ON'
ELSE 'OFF'
END B1,
CASE WHEN B2 = 1
THEN 'ON'
ELSE 'OFF'
END B2
FROM
DATALOGTABLE WITH (NOLOCK)
WHERE
(CONVERT(DATE, DATEANDTIME, 103) >= CONVERT(DATE, #FROMDATETIME, 103)
AND CONVERT(DATE, DATEANDTIME, 103) <= CONVERT(DATE, #TODATETIME, 103))
AND (((DATEPART(minute, dateandtime) % #intv) = 0))
UNION ALL
SELECT
DATEANDTIME, ALARMTXT ALARM,
NULL F870, NULL F872, NULL F82, NULL F810, NULL F869, NULL F874,
NULL F867, NULL F84, NULL F822, NULL F821, NULL F8X, NULL B1, NULL B2
FROM
DBO.ALARMHISTORY WITH (NOLOCK)
WHERE
(CONVERT(DATE, DATEANDTIME, 103) >= CONVERT(DATE, #FROMDATETIME, 103)
AND CONVERT(DATE, DATEANDTIME, 103) <= CONVERT(DATE, #TODATETIME, 103))
AND (((DATEPART(minute, dateandtime) % #intv) = 0))
) Z
ORDER BY
Z.DATEANDTIME DESC
In the above query I have given time interval of 300 second i.e. 5 minute means value should come after every 300 second or 5 minutes. But it is showing value of every minute.
09 Jan 2020 20:10:59 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:58 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:57 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:56 NULL 70.00 72.00 2.00 0.00 69.65
09 Jan 2020 20:10:55 NULL 70.00 72.00 2.00 0.00 69.65
Here the first record have date '09 Jan 2020 20:10:59' and second should be
'09 Jan 2020 20:15:59' because interval given between two rows date is 300 seconds. which is not coming in this case. What to do here?
You seem try to mod minutes to seconds, you should correct this:
declare #DATETIME DATETIME = '2016-09-21 14:59:30';
declare #INTERVAL NVARCHAR(50) = '300'
select (DATEPART(minute, #DATETIME) * 60 + DATEPART(second, #DATETIME)) % #INTERVAL;
I need to split my one column value in column using delimiter, below is the table structure.
create table #a
(
id int,
timeline varchar(100)
)
insert into #a
values (1, 'Semi Annual Q2 (May/June/July) & Q4 (Nov/Dec/Jan)'),
(2, 'Semi Annual Q1 (Feb/Mar/Apr) & Q3 (Aug/Sep/Oct)'),
(3, 'Annual Q3 (Aug/Sep/Oct)'),
(4, 'Annual Q2 (May/June/July)'),
(5, 'Annual Q4 (Nov/Dec/Jan)'),
(6, 'Semi Annual Q1 (Jan/Feb/Mar) & Q3 (July/Aug/Sep)')
select * from #a
Output I want to split timeline values by ' / ' delimiter and make separate column for separate month and all month should be in sequence, which look like a below sample.
ID M1 M2 M3 M4 M5 M6
---------------------------------------
1 May June July Nov Dec Jan
2 Feb Mar Apr Aug Sep Oct
3 Aug Sep Oct NULL NULL NULL
4 May June July NULL NULL NULL
5 Nov Dec Jan NULL NULL NULL
6 Jan Feb Mar July Aug Sep
So far, I have tried this:
select
timeline,
substring((substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline) - 1)), 1, charindex('/', substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline) - 1)) - 1) as M1,
replace(replace(right(substring(substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline)), 1, charindex(')', substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline)))), charindex('/', reverse(substring(substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline)), 1, charindex(')', substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline))))), 4)), '/', ''), ')', '') as M3
from
#a;
which is not a code and too tedious also. please help if you have efficient way to do this.
The SplitCSVToTable8K function being used in the following solution, is the same DelimitedSplit8K function mentioned above...
Here's how to use it in the solution:
WITH
cte_ParseTimeline AS (
SELECT
a.id,
rn = ROW_NUMBER() OVER (PARTITION BY a.id ORDER BY sc.ItemNumber),
sc.Item
FROM
#a a
CROSS APPLY dbo.SplitCSVToTable8K(REPLACE(REPLACE(a.timeline, '(', '/'), ')', '/'), '/') sc
WHERE
sc.Item LIKE ('[A-Z][a-z][a-z]')
OR
sc.Item LIKE ('[A-Z][a-z][a-z][a-z]')
)
SELECT
pt.id,
M1 = MAX(CASE WHEN pt.rn = 1 THEN pt.Item END),
M2 = MAX(CASE WHEN pt.rn = 2 THEN pt.Item END),
M3 = MAX(CASE WHEN pt.rn = 3 THEN pt.Item END),
M4 = MAX(CASE WHEN pt.rn = 4 THEN pt.Item END),
M5 = MAX(CASE WHEN pt.rn = 5 THEN pt.Item END),
M6 = MAX(CASE WHEN pt.rn = 6 THEN pt.Item END)
FROM
cte_ParseTimeline pt
GROUP BY
pt.id;
Results...
id M1 M2 M3 M4 M5 M6
----------- ----- ----- ----- ----- ----- -----
1 May June July Nov Dec Jan
2 Feb Mar Apr Aug Sep Oct
3 Aug Sep Oct NULL NULL NULL
4 May June July NULL NULL NULL
5 Nov Dec Jan NULL NULL NULL
6 Jan Feb Mar July Aug Sep
I have following table of Employee details
EmployeeName CompayId CompanyLastActive
---------------------------------------------------------
robort 112 10 Jun 2015 09:30
john 113 11 Jun 2015 11:10
sunny 114 14 Jun 2015 16:10
sumanth 114 15 Jun 2015 18:11
usha 115 07 Jun 2015 13:14
sudheer 115 14 Jun 2015 17:10
sweety 115 08 Jun 2015 16:34
I need to get the latest employee active time based on CompanyID with Comma separated EmployeeName like below
EmployeeName CompayId CompanyLastActive
---------------------------------------------------------
robort 112 10 Jun 2015 09:30
john 113 11 Jun 2015 11:10
sunny, sumanth 114 15 Jun 2015 18:11
usha, sudheer, sweety 115 14 Jun 2015 17:10
please help me how to solve.
SELECT EmployeeName = STUFF((
SELECT ',' + e1.EmployeeName
FROM dbo.Employee e1
WHERE e.CompayId = e1.CompayId
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, ''),
e.CompayId,
MAX(CompanyLastActive) as CompanyLastActive
FROM dbo.Employee e
GROUP BY e.CompayID
ORDER BY e.CompayId
Result:
EmployeeName CompayId CompanyLastActive
-------------------------------------------------------
robort 112 June, 10 2015 09:30:00
john 113 June, 11 2015 11:10:00
sunny,sumanth 114 June, 15 2015 18:11:00
usha,sudheer,sweety 115 June, 14 2015 17:10:00
Sample result in SQL Fiddle.
Check this out, i have not checked this as i'm feeling lazy to build schema, it would probably throw group by error, You can handle it
SELECT
Results.CompayId,
STUFF((
SELECT ', ' + CAST(EmployeeName AS VARCHAR(MAX))
FROM YourTable
WHERE (ID = Results.ID)
FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
,1,2,'') AS NameValues
,max(Results.CompanyLastActive) as CompanyLastActive
FROM YourTable Results
GROUP BY CompayId
You can use this query:
SELECT EmployeeNames = dbo.EmployeeNamesPerCompany(CompanyID,', '),
CompanyID,
CompanyLastActive = MAX(CompanyLastActive)
FROM Employee e
GROUP BY CompanyID
ORDER BY MAX(CompanyLastActive)
If you have created a scalar valued function like this:
CREATE FUNCTION [dbo].[EmployeeNamesPerCompany]
(
#companyID Int,
#delimiter varchar(5)
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #Names VARCHAR(8000)
SELECT #Names = COALESCE(#Names + #delimiter, '') + e.EmployeeName
FROM Employee e
WHERE e.CompanyId = #companyID
ORDER BY e.EmployeeName
return #Names
END
Sql-Fiddle Demo
I would like to get the list of available time for the given date and duration form the tblAppointments table
tblAppointments
id int
BookingDate datetime
BookedStartTime datetime
BookedEndTime datetime
Sample Data in the table
id BookingDate BookedStartTime BookedEndTime
1 2014-02-03 00:00:00 2014-02-03 08:30:00 2014-02-03 09:00:00
2 2014-02-03 00:00:00 2014-02-03 09:00:00 2014-02-03 10:30:00
3 2014-02-03 00:00:00 2014-02-03 12:00:00 2014-02-03 14:30:00
4 2014-02-03 00:00:00 2014-02-03 15:00:00 2014-02-03 16:30:00
If I give a input parameters as
BookingDate : 2014-02-03
DurationCode : 1 (eg 30 minutes)
I would like to get the result as below
2014-02-03 08:00:00 2014-02-03 08:30:00
2014-02-03 10:30:00 2014-02-03 11:00:00
2014-02-03 11:00:00 2014-02-03 11:30:00
2014-02-03 11:30:00 2014-02-03 12:00:00
2014-02-03 14:30:00 2014-02-03 15:00:00
2014-02-03 16:30:00 2014-02-03 17:00:00
If the input parameters are
BookingDate : 2014-02-03
DurationCode : 2 (eg 15 minutes)
The results should be like given below
2014-02-03 08:00:00 2014-02-03 08:15:00
2014-02-03 08:15:00 2014-02-03 08:30:00
2014-02-03 10:30:00 2014-02-03 10:45:00
2014-02-03 10:45:00 2014-02-03 11:00:00
2014-02-03 11:00:00 2014-02-03 11:15:00
2014-02-03 11:15:00 2014-02-03 11:30:00
2014-02-03 11:30:00 2014-02-03 11:45:00
2014-02-03 11:45:00 2014-02-03 12:00:00
2014-02-03 14:30:00 2014-02-03 14:45:00
2014-02-03 14:45:00 2014-02-03 15:00:00
2014-02-03 16:30:00 2014-02-03 16:45:00
2014-02-03 16:45:00 2014-02-03 17:00:00
The start and end appointment are 08:00 and 18:00
I have written a stored procedure for the same, which seems to be working, but I would like to know if there is any simple way to do the same.
The Stored Procedure is
ALTER Procedure [dbo].[FindAvailableTime] (
#BookingDate datetime,
#DurationCode int
)
as
Declare #Duration datetime
Declare #DurationMinutes int
Declare #DurationHours int
select #Duration = Duration from DurationCode where DurationCodeID = #DurationCode
Set #DurationMinutes = datepart(minute,#Duration)
Set #DurationHours = datepart(hour,#Duration)
if (#DurationHours > 0)
Begin
Set #DurationMinutes = #DurationMinutes + (#DurationHours * 60)
End
Declare #StartTimeHR int
Declare #StartTimeMN int
Declare #EndTimeHR int
Declare #EndTimeMN int
Declare #CurrentDateTimeStart datetime
Declare #CurrentDateTimeStartString varchar(100)
Declare #CurrentDateTimeEnd datetime
Declare #CurrentDateTimeEndString varchar(100)
Declare #CurrentDateTimeEndWork datetime
Declare #CurrentDateTimeEndStringWork varchar(100)
Declare #CurrentYear int
Declare #CurrentMonth int
Declare #CurrentDay int
Set #CurrentYear = datepart(year,#BookingDate)
Set #CurrentMonth = datepart(month,#BookingDate)
Set #CurrentDay = datepart(day,#BookingDate)
Set #StartTimeHR = 8
Set #StartTimeMN = 0
Set #EndTimeHR = 18
Set #EndTimeMN = 1
Set #CurrentDateTimeStartString = convert(varchar(10),#CurrentYear) + '-' + convert(varchar(10),#CurrentMonth) + '-' + convert(varchar(10),#CurrentDay) + ' ' + convert(varchar(10),#StartTimeHR) + ':' + convert(varchar(10),#StartTimeMN) + ':' + '0'
Set #CurrentDateTimeEndString = convert(varchar(10),#CurrentYear) + '-' + convert(varchar(10),#CurrentMonth) + '-' + convert(varchar(10),#CurrentDay) + ' ' + convert(varchar(10),#EndTimeHR) + ':' + convert(varchar(10),#EndTimeMN) + ':' + '0'
set #CurrentDateTimeStart = convert(datetime, #CurrentDateTimeStartString)
set #CurrentDateTimeEnd = convert(datetime, #CurrentDateTimeEndString)
Declare #CurrentDateTimeEndTemp datetime
set #CurrentDateTimeEndTemp = dateadd(mi,#DurationMinutes,#CurrentDateTimeStart)
Declare #AppointmentStartTime datetime
Declare #AppointmentEndTime datetime
Declare #StartDate datetime
Declare #EndDate datetime
Declare #EndDateTemp datetime
Declare #StartDatePlusOne datetime
Declare #EndDateMinusOne datetime
set #StartDate = #CurrentDateTimeStart
set #EndDate = #CurrentDateTimeEnd
set #EndDateTemp = dateadd(mi,#DurationMinutes,#StartDate)
Set #StartDatePlusOne = dateadd(mi,1,#StartDate)
Set #EndDateMinusOne = DateAdd(mi,-1,#EndDateTemp)
Create Table #Appointment_AvailableTime (StartTime datetime, EndTime datetime)
if Exists (select * from tblAppointments where BookingDate = #BookingDate)
Begin
while (#EndDateTemp < #EndDate)
Begin
if not exists (Select * from tblAppointments where #StartDatePlusOne between BookedStartTime and BookedEndTime or #EndDateMinusOne between BookedStartTime and BookedEndTime)
begin
if not exists (Select * from tblAppointments where BookedStartTime Between #StartDatePlusOne and #EndDateMinusOne or BookedEndTime between #StartDatePlusOne and #EndDateMinusOne)
Begin
insert into #Appointment_AvailableTime values(#StartDate, #EndDateTemp)
set #StartDate = dateadd(mi,#DurationMinutes,#StartDate)
End
Else
Begin
Select #StartDate = max(BookedEndTime) from tblAppointments where BookedStartTime Between #StartDatePlusOne and #EndDateMinusOne or BookedEndTime between #StartDatePlusOne and #EndDateMinusOne
End
set #EndDateTemp = dateadd(mi,#DurationMinutes,#StartDate)
Set #StartDatePlusOne = dateadd(mi,1,#StartDate)
Set #EndDateMinusOne = DateAdd(mi,-1,#EndDateTemp)
End
Else
Begin
Select #StartDate = max(BookedEndTime) from tblAppointments where #StartDatePlusOne between BookedStartTime and BookedEndTime or #EndDateMinusOne between BookedStartTime and BookedEndTime
set #EndDateTemp = dateadd(mi,#DurationMinutes,#StartDate)
Set #StartDatePlusOne = dateadd(mi,1,#StartDate)
Set #EndDateMinusOne = DateAdd(mi,-1,#EndDateTemp)
End
End
End
Else
Begin
Set #CurrentDateTimeEndWork = dateadd(mi,#DurationMinutes,#CurrentDateTimeStart)
while (#CurrentDateTimeStart < #CurrentDateTimeEnd and #CurrentDateTimeEndWork < #CurrentDateTimeEnd)
Begin
insert into #Appointment_AvailableTime values(#CurrentDateTimeStart, #CurrentDateTimeEndWork)
set #CurrentDateTimeStart = dateadd(mi,#DurationMinutes,#CurrentDateTimeStart)
Set #CurrentDateTimeEndWork = dateadd(mi,#DurationMinutes,#CurrentDateTimeStart)
End
End
select StartTime, EndTime from #Appointment_AvailableTime
Thanks
Maintain a table that holds all valid appointment times. Putting all possible 1h, 30m, 15m slots during an 10 hour period is still tiny (70 rows). This makes adding more complex rules, like "no 1 hour appointments after 4pm" really easy. Adding a day-of-the-week column to the lookup table will let you trivially add things like "extended hours on wednesdays" or "half day saturdays".
CREATE TABLE tblAppointmentSlots (
DurationID int,
SlotStartTime datetime CHECK (CAST(SlotStartTime AS int) = 0),
SlotEndTime datetime CHECK (CAST(SlotEndTime AS int) = 0)
)
GO
INSERT tblAppointmentSlots VALUES
(1, '08:00', '08:30'),
(1, '08:30', '09:00'),
etc..
GO
ALTER Procedure [dbo].[FindAvailableTime] (
#BookingDate datetime,
#DurationCode int
)
AS
SELECT
#BookingDate + SlotStartTime,
#BookingDate + SlotEndTime
FROM tblAppointmentSlots
WHERE DurationID = #DurationCode
AND NOT EXISTS (
SELECT 1
FROM tblAppointments
WHERE #BookingDate + SlotStartTime < BookedEndTime
AND #BookingDate + SlotEndTime > BookedStartTime
)
I have 3 Columns in db Time Parameter(00:15) , StartTime(09:00) , EndTime (15:00)
Now I want to show all time with gap of 00:15 min between 09:00 and 15:00
What query should I write so that it returns values something like this:
09:00 - 09:15
09:15 - 09:30
09:30 - 09:45
-
-
-
-
14:45 - 15:00
Using CTE and assuming hour part of #time is zero:
declare #time time(0) = '00:15',
#start time(0) = '12:00',
#end time(0) = '15:00'
;with cte as (
select #start sTime, dateadd(minute, datepart(minute,#time), #start) eTime
union all
select eTime, dateadd(minute, datepart(minute,#time), eTime)
from cte
where dateadd(minute, datepart(minute,#time), eTime) <= #end
)
select left(sTime,5) + ' - ' + left(eTime, 5) results
from cte
--results
12:00 - 12:15
12:15 - 12:30
12:30 - 12:45
12:45 - 13:00
13:00 - 13:15
13:15 - 13:30
13:30 - 13:45
13:45 - 14:00
14:00 - 14:15
14:15 - 14:30
14:30 - 14:45
14:45 - 15:00
Use a Common table expression (CTE) to generate a table with all the times in it that you want.
Declare #strtDt smallDatetime = '15 May 2013 09:00';
Declare #endDt smallDateTime = '15 May 2013 15:00';
With DateTimes(dt) As
(Select #strtDt
Union All
Select DateAdd(minute, 15, dt)
From DateTimes
Where dt < #endDt)
Select dt from DateTimes
option (maxrecursion 10000)