I have written the following stored procedure that uses a Date Dimension table to calculate the next occurrence of a date given a begin date and a frequency.
I am getting some odd syntax errors that seem to occur whenever I have an IF BEGIN SET IF SET END sequence.
In order to help debug, I have gone back in and added unneeded BEGIN and END statements around the one line IF statements.
Am I missing some type of BEGIN - END or IF - ELSE matching rule here? (I've marked the lines that the parser is complaining about with comments.)
CREATE PROCEDURE dbo.GetNextScheduledBusinessDayOccurance
(
#BeginDate DATE,
#Frequency CHAR(1)
)
AS
BEGIN
DECLARE #Date DATETIME,
#currentDate DATE,
#weekOfYear INT,
#dayOfWeek varchar(9),
#weekOfMonth tinyint,
#month varchar(2),
#dayOfQuarter tinyint,
#currentDayOfQuarter tinyint,
#quarterOfNextOccurance tinyint,
#yearOfNextOccurance int;
SET #currentDate = CONVERT(Date, GETDATE())
IF (#BeginDate > #currentDate)-- If it hasn't started yet
BEGIN
SET #Date = (SELECT TOP(1) [DATE] FROM dbo.dim_Date WHERE [DATE] >= #BeginDate AND [Date] > #currentDate AND (IsBusinessDay = 1) ORDER BY [DATE])
END
ELSE
BEGIN
IF #Frequency = 'A' --Annually
BEGIN
SET #Date = (SELECT TOP(1) [DATE] FROM dbo.dim_Date WHERE ([DATE] > #currentDate AND [Month] >= DATEPART(MONTH, #BeginDate) AND [Day] >= DATEPART(DAY, #BeginDate) AND IsBusinessDay = 1) ORDER BY [Date])
END
ELSE IF #Frequency = 'B' --Biweekly
BEGIN
SET #weekOfYear = (SELECT WeekOfYear FROM dbo.dim_Date WHERE [Date] = #BeginDate)
SET #dayOfWeek = (SELECT [DayOfWeek] FROM Dbo.dim_Date WHERE [Date] >= #BeginDate AND IsBusinessDay = 1)
SET #Date = ((SELECT TOP(1) [Date] FROM dbo.dim_Date WHERE ([DATE] > #currentDate AND [WeekOfYear]%2 = #weekOfYear%2 AND [DayOfWeek] = #dayOfWeek AND IsBusinessDay = 1) ORDER BY [Date]))
END
ELSE IF #Frequency = 'D' --Daily
BEGIN
SET #Date = ((SELECT TOP(1) [Date] FROM dbo.dim_Date WHERE ([DATE] > #currentDate AND IsBusinessDay = 1) ORDER BY [Date]))
END
ELSE IF #Frequency = 'E' -- Semi-Monthly (twice each month) (assume the 15th and last day of month)
BEGIN
-- GET the next 15th or last day of month.
SET #Date = (SELECT TOP(1) [Date] FROM dim_Date WHERE [Date] > #currentDate AND (Day = '15' OR (DateAdd(day, -1, DateAdd( month, DateDiff(month , 0,[Date])+1 , 0)) = [Date])) ORDER BY [Date])
IF ((SELECT IsBusinessDay FROM dim_Date WHERE [Date] = #Date) = 0)
BEGIN
SET #Date = ((SELECT TOP(1) [Date] FROM dbo.dim_Date WHERE (([DATE] > #Date) AND IsBusinessDay = 1) ORDER BY [Date])
END --Parser ERROR: Incorrect syntax near the keyword 'END'.
END
ELSE IF #Frequency = 'I' --Bimonthly (Every other month)
BEGIN
SET #Month = (SELECT Month FROM dbo.dim_Date WHERE [Date] = #BeginDate)
SET #Date = (SELECT TOP(1) [Date] FROM dbo.dim_Date WHERE ([Date] > #currentDate AND [Month]%2 = #Month%2 AND [Day] = DATEPART(day, #BeginDate)) ORDER BY [Date])
IF ((SELECT IsBusinessDay FROM dim_Date WHERE [Date] = #Date) = 0)
BEGIN
SET #Date = ((SELECT TOP(1) [Date] FROM dbo.dim_Date WHERE (([DATE] > #Date) AND IsBusinessDay = 1) ORDER BY [Date])
END --Parser ERROR: Incorrect syntax near the keyword 'END'.
END
ELSE IF #Frequency = 'L' --Last Business Day of the Month
BEGIN
SET #Date = (SELECT TOP(1) [Date] FROM dim_Date WHERE [Date] > '2013-03-20 00:00:00.000' AND (DateAdd(day, -1, DateAdd( month, DateDiff(month , 0,[Date])+1 , 0)) = [Date]) ORDER BY [Date])
IF ((SELECT IsBusinessDay FROM dim_Date WHERE [Date] = #Date) = 0)
BEGIN
SET #Date = ((SELECT TOP(1) [Date] FROM dbo.dim_Date WHERE (([DATE] < #Date) AND IsBusinessDay = 1) ORDER BY [Date] DESC))
END
END
ELSE IF #Frequency = 'M' -- Monthly
BEGIN
SET #Date = (SELECT TOP(1) [Date] FROM dim_Date WHERE [Date] > #currentDate AND (Day > DATEPART(day, #BeginDate)) ORDER BY [Date])
IF ((SELECT IsBusinessDay FROM dim_Date WHERE [Date] = #Date) = 0)
BEGIN
SET #Date = ((SELECT TOP(1) [Date] FROM dbo.dim_Date WHERE (([DATE] > #Date) AND IsBusinessDay = 1) ORDER BY [Date])
END--Parser ERROR: Incorrect syntax near the keyword 'END'.
END
ELSE
IF #Frequency = 'Q' --Quarterly
BEGIN
SET #dayOfQuarter = (Select DayOfQuarter FROM dim_Date WHERE [DATE] = #BeginDate)
SET #currentDayOfQuarter = (Select DayOfQuarter FROM dim_Date WHERE [DATE] = #currentDate)
SET #quarterOfNextOccurance = (SELECT [Quarter] FROM dbo.dim_Date WHERE [Date] = #currentDate)
SET #yearOfNextOccurance = (SELECT [Year] FROM dbo.dim_Date WHERE [Date] = #currentDate)
--SELECT #dayOfQuarter DOQ, #currentDayOfQuarter curDOQ, #quarterOfNextOccurance QofNext, #yearOfNextOccurance YofNext
IF (#currentDayOfQuarter >= #dayOfQuarter)
SET #quarterOfNextOccurance = #quarterOfNextOccurance + 1
SET #Date = '1900-01-01'
WHILE (#Date < #currentDate) --Loop through this just in case we're close to the end of the Quarter, and there's no more business days left
BEGIN
IF (#quarterOfNextOccurance > 4)
BEGIN
SET #quarterOfNextOccurance = #quarterOfNextOccurance%4
SET #yearOfNextOccurance = #yearOfNextOccurance + 1
END
--SELECT #quarterOfNextOccurance QofNext, #yearOfNextOccurance YofNext
--CREATE a temp table with all of the business dates from the target quarter in decending order.
SELECT * INTO ##temp FROM (SELECT TOP(92) [Date], MAX(DayOfQuarter) as DOQ FROM dim_Date WHERE (YEAR = #yearOfNextOccurance AND Quarter = #quarterOfNextOccurance AND IsBusinessDay = 1) Group By Date ORDER BY Date DESC) as foo
SET #Date = (SELECT TOP(1) DATE from ##temp WHERE DOQ <= #dayOfQuarter)
SET #quarterOfNextOccurance = #quarterOfNextOccurance + 1 -- Go ahead and incriment this just in case we start the WHILE over.
--SELECT * FROM ##temp
BEGIN TRY DROP TABLE ##temp END TRY BEGIN CATCH END CATCH
END
END
ELSE
IF #Frequency = 'S' --Semi-annually
BEGIN
SET #Date = #BeginDate
WHILE (#Date < #currentDate)
BEGIN
SET #Date = (SELECT [Date] FROM dbo.dim_Date WHERE [Date] = DATEADD(MONTH, 6, #Date))
END
IF ((SELECT IsBusinessDay FROM dim_Date WHERE [Date] = #Date) = 0)
BEGIN
SET #Date = ((SELECT TOP(1) [Date] FROM dbo.dim_Date WHERE (([DATE] > #Date) AND IsBusinessDay = 1) ORDER BY [Date])
END--Parser ERROR: Incorrect syntax near the keyword 'END'.
END
ELSE
IF #Frequency = 'W' --Weekly
BEGIN
SET #dayOfWeek = (SELECT [DayOfWeek] FROM dbo.dim_Date WHERE [Date] = #BeginDate)
SET #Date = (SELECT TOP(1) [Date] FROM Dbo.dim_Date WHERE DayOfWeek = #dayOfWeek AND [DATE] < #currentDate ORDER BY [DATE] DESC)
--SELECT #Date DATE, #BeginDate BeginDate
WHILE ((#Date < #currentDate) OR (#Date < #BeginDate))
BEGIN
SET #Date = (SELECT [Date] FROM dbo.dim_Date WHERE [Date] = DATEADD(Week, 1, #Date))
--SELECT #Date DateInWHile
END
IF ((SELECT IsBusinessDay FROM dim_Date WHERE [Date] = #Date) = 0)
SET #Date = (SELECT TOP(1) [Date] FROM dbo.dim_Date WHERE (([DATE] > #Date) AND IsBusinessDay = 1) ORDER BY [Date])
--SELECT #Date
END
ELSE
SET #Date = NULL
END
RETURN #Date
END
GO
You're missing a closing ):
BEGIN
SET #Date = ((
SELECT TOP(1) [Date]
FROM dbo.dim_Date
WHERE (([DATE] > #Date) AND IsBusinessDay = 1)
ORDER BY [Date]) ) -- Paren added here...
END --Parser ERROR: Incorrect syntax near the keyword 'END'.
Related
I have the following query
Create procedure usp_GetBills
#PageNo INT = 1,
#PageSize INT = 10,
#SortOrder INT = 1,
#SortColumn VARCHAR(20) = ''
AS
BEGIN
DECLARE
#lSortColumn VARCHAR(20),
#lFirstRec INT,
#lLastRec INT
SET #SortColumn = LTRIM(RTRIM(#SortColumn))
SET #lFirstRec = (#PageNo - 1) *#PageSize
SET #lLastRec = (#PageNo * #PageSize + 1)
;WITH CTE_Results
AS(
SELECT ROW_NUMBER() OVER (ORDER BY(
#SortColumn))
AS ROWNUM,P.BillNo, P.PropertyNo, P.BillDate, P.BillFromDate, P.BillToDate, P.BillAmount, P.DueDate, P.Status
FROM Bill P)
SELECT * from CTE_Results
WHERE ROWNUM > #lFirstRec
AND ROWNUM < #lLastRec
ORDER BY
--ROWNUM * #SortOrder
CASE WHEN #SortOrder = 1 THEN #SortColumn ELSE '' END ASC,
CASE WHEN #SortOrder = 2 THEN #SortColumn ELSE '' END DESC
END
And so if I exec
DECLARE #return_value int
EXEC #return_value = [dbo].[usp_GetBills]
#PageNo = 2,
#PageSize = 10,
#SortOrder = N'1',
#SortColumn = 'BillNo'
SELECT 'Return Value' = #return_value
This query gives me the same result always w.r.t SortOrder. The SortOrder doesn't seems to work properly. I referred this link
Thanks.
we cant pass dynamic columns in order by clause
So this
Create procedure usp_GetBills
#PageNo INT = 1,
#PageSize INT = 10,
#SortOrder INT = 1,
#SortColumn VARCHAR(20) = ''
AS
BEGIN
DECLARE
#lSortColumn VARCHAR(20),
#lFirstRec INT,
#lLastRec INT
SET #SortColumn = LTRIM(RTRIM(#SortColumn))
SET #lFirstRec = (#PageNo - 1) *#PageSize
SET #lLastRec = (#PageNo * #PageSize + 1)
;WITH CTE_Results
AS(
SELECT ROW_NUMBER() OVER (ORDER BY(
#SortColumn))
AS ROWNUM,P.BillNo, P.PropertyNo, P.BillDate, P.BillFromDate, P.BillToDate, P.BillAmount, P.DueDate, P.Status
FROM Bill P)
SELECT * from CTE_Results
WHERE ROWNUM > #lFirstRec
AND ROWNUM < #lLastRec
ORDER BY
--ROWNUM * #SortOrder
CASE WHEN #SortIndex = 1 THEN BillNo END ASC,
CASE WHEN #SortIndex = 2 THEN BillNo END DESC,
CASE WHEN #SortIndex = 1 THEN PropertyNo END ASC
CASE WHEN #SortIndex = 2 THEN PropertyNo END DESC
END
I'm relatively new to SQL, but am generally a quick learner and this particular query has stumped me for a few days. Any help would be beyond appreciated at this point.
When I run the below query, I only return rows where there exists a statusdatetime (the agent logged in that day). I need to return a row even when the agent didn't log in but was scheduled. How can I change this query to return a NULL for that. I thought the left join would work.
DECLARE #startDate datetime
DECLARE #endDate datetime
SET #startDate = GETDATE()
SET #endDate = GETDATE()
SET #startDate = CONVERT(DATETIME, CONVERT(varchar(11),#startDate, 111 ) + ' 00:00:00', 111)
SET #endDate = CONVERT(DATETIME, CONVERT(varchar(11),#endDate, 111 ) + ' 23:59:59', 111)
Begin
Create table #boris5table(
Firstname varchar(50),
lastname varchar (50),
username varchar (50),
starttime datetime,
loggedintime datetime,
variation int)
End
Insert into #boris5table (Firstname, lastname, username, starttime, loggedintime, variation)
Select firstname, lastname, userid,
(cast(DATEADD(MINUTE, (-300 +
(select min(startoffset) from [dbo].[IO_ScheduleInterval]
Where activitytypeid = '0000000000000000000004'
and PaidTime = '1'
and f1.agentid = f2.agentid
and ScheduleID = f1.scheduleid)), StartDateTimeUTC) as datetime)),
case when exists (select count(*), statusdatetime from [dbo].[AgentActivityLog] Where StatusDateTime between #startdate and #enddate Group by StatusDateTime) then min(statusdatetime)
Else NULL
End as LoggedInTime,
DATEDIFF(minute, (cast(DATEADD(MINUTE, (-300 +
(select min(startoffset) from [dbo].[IO_ScheduleInterval]
Where activitytypeid = '0000000000000000000004'
and PaidTime = '1'
and f1.agentid = f2.agentid
and ScheduleID = f1.scheduleid)), StartDateTimeUTC) as datetime)),
case when exists (select statusdatetime from [dbo].[AgentActivityLog] Where StatusDateTime between #startdate and #enddate and f3.UserId = f2.UserName) then min(statusdatetime)
Else 'NULL' END)
as 'Variation (minutes)'
From [I3_IC].[dbo].[IO_Schedule] as f1
left join [dbo].[IO_Agent] as f2 on f1.AgentID = f2.AgentID and (CAST(DATEADD(hour, - 5, f1.StartDateTimeUTC) as date)) between #startdate and #enddate
left join [dbo].[Individual] as f4 on f2.UserName = f4.WebLogin and LastName <> '-'
left join [dbo].[AgentActivityLog] as f3 on f2.UserName = f3.UserId and (CAST(DATEADD(hour, -1, f3.StatusDateTime) as date)) between #startdate and #enddate
Group by firstname, lastname, f2.UserName, ScheduleID, f1.AgentID, f2.AgentID, StartDateTimeUTC, f3.UserId
Select *
From #boris5table
drop table #boris5table
I need this report to be modify show that it shows these calculations for each month. Currently not sure how. I have declared a start and end date that is monthly, but that might need to be changed.
declare #dataset_name varchar(36), #start_date datetime, #end_date date #report_date int, #start_date2 datetime, #end_date2 datetime, #report_date2 int
--set #dataset_name = 'Atlanta OPHC' -- This can be used to search individual business units --
set #start_date = '7/1/14' -- ENTER REPORT START DATE--
set #end_date = '7/31/14' -- ENTER REPORT END DATE---
set #start_date2 = '6/1/14' -- ENTER REPORT START DATE--
set #end_date2 = '6/30/14' -- ENTER REPORT END DATE---
--- Do Not Change anything below---
set #report_date = DATEDIFF(DD,#start_date , #end_date + 1)
set #report_date2 = DATEDIFF(DD,#start_date2 , #end_date2 + 1)
select tot.DATASET_NAME, SUM(tot.LENGTH_OF_STAY) as TOTAL_LOS, SUM(tot.LENGTH_OF_STAY)/ #report_date as Avg_daily_census, #start_date, #end_date,
COUNT(length_of_stay) as clients_servered,
AVG(tot.LENGTH_OF_STAY) as avg_los,
Count(admit_count) as Total_admission,
Count(discharge_date) as Total_discharge,
COUNT(active_patients)as Active_patients,
SUM(tot.LENGTH_OF_STAY2) as TOTAL_LOS2, SUM(tot.LENGTH_OF_STAY2)/ #report_date2 as Avg_daily_census2, #start_date2, #end_date2,
COUNT(length_of_stay2) as clients_servered2,
AVG(tot.LENGTH_OF_STAY2) as avg_los2,
Count(admit_count2) as Total_admission2,
Count(discharge_date2) as Total_discharge2,
COUNT(active_patients2)as Active_patients2
from (select od.DATASET_NAME,
DATEDIFF(DD,
case when pa.ADMIT_DATE < #start_date then #start_date else pa.ADMIT_DATE end,
case when ISNULL(pa.TERMINATION_DATE,GETDATE()) > #end_date then #end_date else ISNULL(pa.TERMINATION_DATE,GETDATE()) end)
+ 1 as LENGTH_OF_STAY,
case when pa.ADMIT_DATE between #start_date and #end_date then 1 end as admit_count,
case when pa.TERMINATION_DATE between #start_date and #end_date then 1 end as discharge_date,
case when pa.ADMIT_DATE <= #start_date or pa.ADMIT_DATE <= #end_date and TERMINATION_DATE IS NULL then 1 end as active_patients,
DATEDIFF(DD,
case when pa.ADMIT_DATE < #start_date2 then #start_date2 else pa.ADMIT_DATE end,
case when ISNULL(pa.TERMINATION_DATE,GETDATE()) > #end_date2 then #end_date2 else ISNULL(pa.TERMINATION_DATE,GETDATE()) end)
+ 1 as LENGTH_OF_STAY2,
case when pa.ADMIT_DATE between #start_date2 and #end_date2 then 1 end as admit_count2,
case when pa.TERMINATION_DATE between #start_date2 and #end_date2 then 1 end as discharge_date2,
case when pa.ADMIT_DATE <= #start_date2 or pa.ADMIT_DATE <= #end_date2 and TERMINATION_DATE IS NULL then 1 end as active_patients2
from PT_ADMISSION pa
join PT_BASIC pb on pa.PATIENT_ID = pb.PATIENT_ID
join O_DATASET od on pb.DATASET_ID = od.DATASET_ID
where (od.DATASET_NAME = #dataset_name or DATASET_NAME NOT IN ('Atlanta Training','Initial Configuration Home Health','Initial Configuration Hospice','Initial Configuration Private Duty','Penetration Testing'))
and pa.ADMIT_DATE <= #end_date
and ISNULL(pa.TERMINATION_DATE,GETDATE()) >= #start_date) tot
group by tot.DATASET_NAME
Without an ability to test it, it looks basically fine.
However I would never rely on d/m/yy for those dates. The safest format for date literals in SQL Server is YYYYMMDD, next best is YYYY-MM-DD
I might have called set #report_date & set #report_date2 (which aren't storing dates)
#report_duration & #report_duration2
There's a comma missing in the first line above after #end_date date
I reformatted to read the query, it may help others too:
DECLARE #dataset_name varchar(36)
, #start_date datetime
, #end_date date
, #report_date int
, #start_date2 datetime
, #end_date2 datetime
, #report_date2 int
--set #dataset_name = 'Atlanta OPHC' -- This can be used to search individual business units --
SET #start_date = '20140701' -- ENTER REPORT START DATE--
SET #end_date = '20140731' -- ENTER REPORT END DATE---
SET #start_date2 = '20140601' -- ENTER REPORT START DATE--
SET #end_date2 = '20140630' -- ENTER REPORT END DATE---
--- Do Not Change anything below---
SET #report_date = DATEDIFF(DD, #start_date, #end_date + 1)
SET #report_date2 = DATEDIFF(DD, #start_date2, #end_date2 + 1)
SELECT
tot.DATASET_NAME
, SUM(tot.LENGTH_OF_STAY) AS TOTAL_LOS
, SUM(tot.LENGTH_OF_STAY) / #report_date AS Avg_daily_census
, #start_date
, #end_date
, COUNT(length_of_stay) AS clients_servered
, AVG(tot.LENGTH_OF_STAY) AS avg_los
, COUNT(admit_count) AS Total_admission
, COUNT(discharge_date) AS Total_discharge
, COUNT(active_patients) AS Active_patients
, SUM(tot.LENGTH_OF_STAY2) AS TOTAL_LOS2
, SUM(tot.LENGTH_OF_STAY2) / #report_date2 AS Avg_daily_census2
, #start_date2
, #end_date2
, COUNT(length_of_stay2) AS clients_servered2
, AVG(tot.LENGTH_OF_STAY2) AS avg_los2
, COUNT(admit_count2) AS Total_admission2
, COUNT(discharge_date2) AS Total_discharge2
, COUNT(active_patients2) AS Active_patients2
FROM (
SELECT
od.DATASET_NAME
, DATEDIFF(DD,
CASE
WHEN pa.ADMIT_DATE < #start_date THEN #start_date
ELSE pa.ADMIT_DATE END,
CASE
WHEN ISNULL(pa.TERMINATION_DATE, GETDATE()) > #end_date THEN #end_date
ELSE ISNULL(pa.TERMINATION_DATE, GETDATE()) END)
+ 1 AS LENGTH_OF_STAY
, CASE
WHEN pa.ADMIT_DATE BETWEEN #start_date AND #end_date THEN 1 END AS admit_count
, CASE
WHEN pa.TERMINATION_DATE BETWEEN #start_date AND #end_date THEN 1 END AS discharge_date
, CASE
WHEN pa.ADMIT_DATE <= #start_date OR
pa.ADMIT_DATE <= #end_date AND
TERMINATION_DATE IS NULL THEN 1 END AS active_patients
, DATEDIFF(DD,
CASE
WHEN pa.ADMIT_DATE < #start_date2 THEN #start_date2
ELSE pa.ADMIT_DATE END,
CASE
WHEN ISNULL(pa.TERMINATION_DATE, GETDATE()) > #end_date2 THEN #end_date2
ELSE ISNULL(pa.TERMINATION_DATE, GETDATE()) END)
+ 1 AS LENGTH_OF_STAY2
, CASE
WHEN pa.ADMIT_DATE BETWEEN #start_date2 AND #end_date2 THEN 1 END AS admit_count2
, CASE
WHEN pa.TERMINATION_DATE BETWEEN #start_date2 AND #end_date2 THEN 1 END AS discharge_date2
, CASE
WHEN pa.ADMIT_DATE <= #start_date2 OR
pa.ADMIT_DATE <= #end_date2 AND
TERMINATION_DATE IS NULL THEN 1 END AS active_patients2
FROM PT_ADMISSION pa
JOIN PT_BASIC pb
ON pa.PATIENT_ID = pb.PATIENT_ID
JOIN O_DATASET od
ON pb.DATASET_ID = od.DATASET_ID
WHERE (od.DATASET_NAME = #dataset_name
OR DATASET_NAME NOT IN ( 'Atlanta Training'
, 'Initial Configuration Home Health'
, 'Initial Configuration Hospice'
, 'Initial Configuration Private Duty'
, 'Penetration Testing')
)
AND pa.ADMIT_DATE <= #end_date
AND ISNULL(pa.TERMINATION_DATE, GETDATE()) >= #start_date
) tot
GROUP BY
tot.DATASET_NAME
The predicate
AND ISNULL(pa.TERMINATION_DATE, GETDATE()) >= #start_date
might perform better like this:
AND (pa.TERMINATION_DATE >= #start_date OR pa.TERMINATION_DATE IS NULL)
use of functions on columns in the where clause can remove use of an index, so a "sargable" predicate is preferred.
I want to create a fucntion, but getting error.
below is query:
CREATE FUNCTION WFSlaTimer
(
#OBJECT_PK_ID INT = 110
)
RETURNS TABLE
AS BEGIN
DECLARE
#TIMER_START_ACTIVITY_ID INT,
#TIMER_START_ACTIVITY_COMPLETED_ON DATETIME,
#TIMER_END_ACTIVITY_ID INT,
#TIMER_END_ACTIVITY_COMPLETED_ON DATETIME,
#SLA_TIME_SCHEDULE_IN_DAYS INT,
#SLA_DISPLAY VARCHAR(20),
#START_DATE DATETIME,
#END_DATE DATETIME,
#BUSINESS_START_TIME VARCHAR(10),
#BUSINESS_END_TIME VARCHAR(10),
#BUSINESS_HOURS INT,
#SLA_CUT_OFF_TIME VARCHAR(10),
#IS_OBJECT_STATUS_IS_TERMINAL INT,
#COMPLETED_ACTION_ID INT,
#UNCHECKED_ACTION_ID INT,
#DAY_ADDED INT
SELECT #IS_OBJECT_STATUS_IS_TERMINAL = CASE when wos.FLG_STATUS_TYPE = 'W' THEN 0 ELSE 1 END
FROM WF.WF_OBJECT_INSTANCE woi
INNER JOIN WF.WF_OBJECT_STATUS wos ON wos.OBJECT_STATUS_ID = woi.OBJECT_STATUS_ID
WHERE woi.LINK_PK_ID = #OBJECT_PK_ID
SET #SLA_TIME_SCHEDULE_IN_DAYS = (SELECT CASE WHEN s.SLA_SCHEDULE_ID = 1 THEN lr.RUSH_NO_OF_DAYS ELSE s.NUM_OF_DAYS END --1= [RUSH]
FROM loan.LOAN_REQUEST lr
INNER JOIN WF.WF_SLA_SCHEDULE s
ON s.SLA_SCHEDULE_ID = ISNULL(lr.SLA_SCHEDULE_ID, 2) --{2= SLA-Schedule 5 Days}
WHERE lr.LOAN_REQUEST_ID = #OBJECT_PK_ID)
SET #SLA_DISPLAY = (SELECT
CASE WHEN s.SLA_SCHEDULE_ID = 1 THEN s.DISPLAY_NAME + ' (' + CAST(lr.RUSH_NO_OF_DAYS AS VARCHAR) + ')' ELSE s.DISPLAY_NAME END --1= [RUSH]
FROM loan.LOAN_REQUEST lr
INNER JOIN WF.WF_SLA_SCHEDULE s
ON s.SLA_SCHEDULE_ID = ISNULL(lr.SLA_SCHEDULE_ID, 2) --{2= SLA-Schedule 5 Days}
WHERE lr.LOAN_REQUEST_ID = #OBJECT_PK_ID)
SET #BUSINESS_START_TIME = (SELECT s.CONFIG_VALUE FROM SYS_CONFIG_ENTRY s WHERE s.NAME = 'BUSINESS_START_TIME')
SET #BUSINESS_END_TIME = (SELECT s.CONFIG_VALUE FROM SYS_CONFIG_ENTRY s WHERE s.NAME = 'BUSINESS_END_TIME')
SET #BUSINESS_HOURS = (SELECT CAST(DATEDIFF(hour, CAST(#BUSINESS_START_TIME AS DATETIME), CAST(#BUSINESS_END_TIME AS DATETIME)) AS INT))
SET #SLA_CUT_OFF_TIME = (SELECT DATEPART(hour, CAST(s.CONFIG_VALUE AS TIME)) FROM SYS_CONFIG_ENTRY s WHERE s.NAME = 'SLA_CUT_OFF_TIME')
SET #COMPLETED_ACTION_ID = (SELECT ACTION_TYPE_ID FROM WF.WF_ACTION_TYPE WHERE NAME = 'ACTIVITY_COMPLETED')
SET #UNCHECKED_ACTION_ID = (SELECT ACTION_TYPE_ID FROM WF.WF_ACTION_TYPE WHERE NAME = 'ACTIVITY_UNCHECKED')
--GET SLA TIMER ACTIVITY IDs
SELECT #TIMER_START_ACTIVITY_ID = t.START_ACTIVITY_ID,
#TIMER_END_ACTIVITY_ID = t.END_ACTIVITY_ID
FROM [WF].WF_TIMER t
WHERE t.NAME = 'SLA_TIMER'
--Get START ACTIVITY ON
SELECT #TIMER_START_ACTIVITY_COMPLETED_ON = ACTION_ON
FROM [WF].WF_OBJECT_ACTIVITY_HISTORY woah
WHERE LINK_PK_ID = #OBJECT_PK_ID
AND woah.ACTIVITY_ID = #TIMER_START_ACTIVITY_ID
AND ACTION_ID = #COMPLETED_ACTION_ID
AND
--{
woah.APPLICATION_HISTORY_ID > ISNULL((SELECT TOP 1 ISNULL(APPLICATION_HISTORY_ID, 0)
FROM WF.WF_OBJECT_ACTIVITY_HISTORY
WHERE LINK_PK_ID = #OBJECT_PK_ID
AND ACTIVITY_ID = #TIMER_START_ACTIVITY_ID
AND ACTION_ID = #UNCHECKED_ACTION_ID
ORDER BY ACTION_ON DESC
), 0)
--}
--AND
----{
--0 = ISNULL((SELECT TOP 1 ISNULL(APPLICATION_HISTORY_ID, 0)
-- FROM WF.WF_OBJECT_ACTIVITY_HISTORY
-- WHERE LINK_PK_ID = #OBJECT_PK_ID
-- AND ACTIVITY_ID = #TIMER_END_ACTIVITY_ID
-- AND ACTION_ID = #COMPLETED_ACTION_ID
-- ORDER BY ACTION_ON DESC), 0)
----}
ORDER BY ACTION_ON DESC
--Get END ACTIVITY ON
SELECT #TIMER_END_ACTIVITY_COMPLETED_ON = ACTION_ON
FROM [WF].WF_OBJECT_ACTIVITY_HISTORY woah
WHERE LINK_PK_ID = #OBJECT_PK_ID
AND woah.ACTIVITY_ID = #TIMER_END_ACTIVITY_ID
AND ACTION_ID = #COMPLETED_ACTION_ID
AND
--{
woah.APPLICATION_HISTORY_ID > ISNULL((SELECT TOP 1 ISNULL(APPLICATION_HISTORY_ID, 0)
FROM WF.WF_OBJECT_ACTIVITY_HISTORY
WHERE LINK_PK_ID = #OBJECT_PK_ID
AND ACTIVITY_ID = #TIMER_END_ACTIVITY_ID
AND ACTION_ID = #UNCHECKED_ACTION_ID
ORDER BY ACTION_ON DESC
), 0)
--}
ORDER BY ACTION_ON DESC
--TO DO
--SET #TIMER_START_ACTIVITY_COMPLETED_ON = '2014-05-15 02:40:21.100'
--SET #TIMER_END_ACTIVITY_COMPLETED_ON = '2014-05-14 12:40:21.100'
SET #START_DATE = #TIMER_START_ACTIVITY_COMPLETED_ON
SET #DAY_ADDED = #SLA_TIME_SCHEDULE_IN_DAYS -- SLA Schedule Days
+ CASE WHEN DATEPART(hour, #TIMER_START_ACTIVITY_COMPLETED_ON) >= #SLA_CUT_OFF_TIME THEN 0 ELSE -1 END -- SLA Cut Off Time
SET #END_DATE = #START_DATE + #DAY_ADDED
--Exclud Holidays
--{
DECLARE #START_ON_DATE DATETIME = CAST(#START_DATE AS DATE)
WHILE #DAY_ADDED > 0
BEGIN
SELECT #END_DATE = #START_ON_DATE + #DAY_ADDED
--COUNT NO OF HOLIDAYS IF FALLING WITHIN START-DATE AND END-DATE
SELECT #DAY_ADDED = COUNT(*) FROM [WF].WF_CALENDAR WC --HOLIDAY LIST
WHERE WC.DATE BETWEEN #START_ON_DATE+1 AND #END_DATE AND (WC.IS_WEEKEND = 1 OR WC.IS_HOLIDAY = 1)
SET #START_ON_DATE = #END_DATE
END
--}
SET #END_DATE = (CAST(CAST(CAST(#END_DATE AS DATE) AS DATETIME) + CAST(#BUSINESS_END_TIME AS TIME) AS DATETIME))
;WITH TIMER_CTE AS (
SELECT #START_DATE AS OBJECT_CREATED_ON,
#END_DATE AS OBJECT_END_ON,
DIFFERENCE_IN_DAYS = DATEDIFF(dd, GETDATE(), #END_DATE),
TODAY_REMAINING_MINUTES =
CASE WHEN CONVERT(VARCHAR(10), #END_DATE, 112) >= CONVERT(VARCHAR(10), GETDATE(), 112)
THEN DATEDIFF(minute, GETDATE(), (CAST(CAST(CAST(GETDATE() AS DATE) AS DATETIME) + CAST(#BUSINESS_END_TIME AS TIME) AS DATETIME)))
ELSE 0 END,
TODAY_REMAINING_HOURS =
CASE WHEN CONVERT(VARCHAR(10), #END_DATE, 112) >= CONVERT(VARCHAR(10), GETDATE(), 112)
THEN (DATEDIFF(minute, GETDATE(), (CAST(CAST(CAST(GETDATE() AS DATE) AS DATETIME) + CAST(#BUSINESS_END_TIME AS TIME) AS DATETIME)))/60)
ELSE 0 END
)
RETURN (
SELECT
IS_SHOW_SLA = CASE WHEN #TIMER_START_ACTIVITY_COMPLETED_ON IS NULL
--OR #IS_OBJECT_STATUS_IS_TERMINAL = 1
--OR #TIMER_START_ACTIVITY_COMPLETED_ON IS NULL
THEN 0
ELSE 1 END,
#START_DATE AS [START_DATE], #END_DATE AS [END_DATE],
SLA_TYPE = #SLA_DISPLAY,
SLA_DUE = CONVERT(VARCHAR(10), CONVERT(DATETIME, tc.OBJECT_END_ON, 1), 101),
#BUSINESS_END_TIME AS BUSINESS_END_TIME,
SLA_START_ACTIVITY_CHECKED_ON = tc.OBJECT_CREATED_ON,
SLA_END_ACTIVITY_CHECKED_ON = #TIMER_END_ACTIVITY_COMPLETED_ON,
SLA_MISSED = CASE WHEN
--TODAY_REMAINING_MINUTES <= 0
--AND CONVERT(VARCHAR(10), #END_DATE, 112) = CONVERT(VARCHAR(10), GETDATE(), 112)
--OR
( GETDATE()> #END_DATE)
OR #TIMER_START_ACTIVITY_COMPLETED_ON IS NULL
THEN 'Missed' ELSE NULL END,
tc.TODAY_REMAINING_HOURS,
tc.TODAY_REMAINING_MINUTES,
LAST_DAY_TIME_REMAINING =
CASE
WHEN #TIMER_END_ACTIVITY_COMPLETED_ON <= #END_DATE THEN 'Successful Completed'
WHEN CONVERT(VARCHAR(10), #END_DATE, 112) = CONVERT(VARCHAR(10), GETDATE(), 112)
THEN
CASE WHEN
tc.TODAY_REMAINING_HOURS <=0 AND tc.TODAY_REMAINING_MINUTES > 0 THEN
CASE WHEN tc.TODAY_REMAINING_MINUTES = 1 THEN CAST(tc.TODAY_REMAINING_MINUTES AS VARCHAR) + ' min remaining'
ELSE CAST(tc.TODAY_REMAINING_MINUTES AS VARCHAR) + ' mins remaining' END
WHEN tc.TODAY_REMAINING_HOURS =1 THEN CAST(tc.TODAY_REMAINING_HOURS AS VARCHAR) + ' hour remaining'
WHEN tc.TODAY_REMAINING_HOURS >1 THEN CAST(tc.TODAY_REMAINING_HOURS AS VARCHAR) + ' hours remaining'
ELSE NULL
END
ELSE NULL
END,
REMAINING_DAYS = CASE WHEN tc.DIFFERENCE_IN_DAYS <=0 THEN '0 day'
WHEN tc.DIFFERENCE_IN_DAYS > 1 THEN CAST(tc.DIFFERENCE_IN_DAYS AS VARCHAR) + ' days '
ELSE CAST(tc.DIFFERENCE_IN_DAYS AS VARCHAR) + ' day ' END
FROM TIMER_CTE tc
)
END;
GO
I am getting this error:
Msg 156, Level 15, State 1, Procedure WFSlaTimer, Line 144
Incorrect syntax near the keyword 'RETURN'.
Msg 178, Level 15, State 1, Procedure WFSlaTimer, Line 144
A RETURN statement with a return value cannot be used in this context.
Msg 102, Level 15, State 31, Procedure WFSlaTimer, Line 189
Incorrect syntax near 'BEGIN'.
Any help please
There are two kind of function that return table. the inline function and multi-statement function. Yours is multi-statement. Here is the syntax for this:
--Transact-SQL Multistatement Table-valued Function Syntax
CREATE FUNCTION [ schema_name. ] function_name
( [ { #parameter_name [ AS ] [ type_schema_name. ] parameter_data_type
[ = default ] [READONLY] }
[ ,...n ]
]
)
RETURNS #return_variable TABLE <table_type_definition>
[ WITH <function_option> [ ,...n ] ]
[ AS ]
BEGIN
function_body
RETURN
END
[ ; ]
For more information refer to CREATE FUNCTION (Transact-SQL) BOL documentation.
You have to define the returned table's structure (fields and data types)
1) Add a variable name to the function definition (#tableVariable in the above example).
2) Fill the table definition (columns and datatypes)
3) Modify your function to insert the result into the defined table variable, then use an empty RETURN statement when the function should return.
1st step
CREATE FUNCTION WFSlaTimer
(
#OBJECT_PK_ID INT = 110
)
RETURNS #tableVariable TABLE (
IS_SHOW_SLA INT,
StartDate DATETIME2,
EndDate DATETIME2
/** List all of your returned columns like when you creating a table **/
)
AS
BEGIN
/** Do your stuff **/
INSERT INTO #tableVariable ( /* field list */) VALUES (/* value list */)
-- OR --
INSERT INTO #tableVariable ( /* field list */)
SELECT /* FieldList */ FROM myCTE
RETURN
END
2nd step
Modify your RETURN () statement like this:
INSERT INTO #tableVanriable (IS_SHOW_SLA , StartDate , EndDate)
SELECT
IS_SHOW_SLA = CASE WHEN #TIMER_START_ACTIVITY_COMPLETED_ON IS NULL
--OR #IS_OBJECT_STATUS_IS_TERMINAL = 1
--OR #TIMER_START_ACTIVITY_COMPLETED_ON IS NULL
THEN 0
ELSE 1 END,
#START_DATE AS [START_DATE], #END_DATE AS [END_DATE],
SLA_TYPE = #SLA_DISPLAY
/** .... **/
FROM TIMER_CTE tc
/** 3rd step **/
RETURN
I need to find start date and end date from specified (1/2/3/4/5) week of month. So that I can get the records where Date_Created comes in specified (1/2/3/4/5) Week.
For example if
I choose 1st week of febuary 2013 then
I want startdate = 2/1/2013 and enddate = 2/2/2013
I choose 2nd week of febuary 2013 then
I want startdate = 2/3/2013 and enddate = 2/9/2013
and similary for rest weeks.
I have SQL Server 2008 at Database Side. If anyone have Idea then Please Share.
Here is a query to get all weeks start and end dates for given month. So you can select from this query week you need:
SQLFiddle example
with C(i) as
( select CAST('2013-02-01' as datetime) i
UNION ALL
select DATEADD (day,1,i) i from C
where DATEADD (day,1,i)
<DATEADD(month,1,'2013-02-01')
), C1 as
(
select DATEPART(WEEK,i)-DATEPART(WEEK,'2013-02-01')+1 WeekOfMonth,i from C
)
select WeekOfMonth,min(i) StartDate, max(i) EndDate from C1 group by WeekOfMonth
I wrote a procedure to solve my problem which will take week no(1/2/3/4/5) as input and will return startdate and enddate
ALTER PROCEDURE dbo.SPGetStartAndEndDateofSpcifiedWeek
#Week int
AS
SET NOCOUNT ON
DECLARE #date DateTime
DECLARE #currdate DateTime
DECLARE #startdate DateTime
DECLARE #enddate DateTime
DECLARE #CurrWeek int
/*SET #date = CONVERT(date,GETDATE())*/
SET #currdate = CONVERT(date,GETDATE())
SET #CurrWeek = datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, GETDATE()), 0)), 0), GETDATE() - 1) + 1
IF (#Week = 1)
BEGIN
IF (#CurrWeek = 1)
BEGIN SET #date = #currdate END
IF (#CurrWeek = 2)
BEGIN SET #date = #currdate - 7 END
IF (#CurrWeek = 3)
BEGIN SET #date = #currdate - 14 END
IF (#CurrWeek = 4)
BEGIN SET #date = #currdate - 21 END
IF (#CurrWeek = 5)
BEGIN SET #date = #currdate - 28 END
END
IF (#Week = 2)
BEGIN
IF (#CurrWeek = 1)
BEGIN SET #date = #currdate + 7 END
IF (#CurrWeek = 2)
BEGIN SET #date = #currdate END
IF (#CurrWeek = 3)
BEGIN SET #date = #currdate - 7 END
IF (#CurrWeek = 4)
BEGIN SET #date = #currdate - 14 END
IF (#CurrWeek = 5)
BEGIN SET #date = #currdate - 21 END
END
IF (#Week = 3)
BEGIN
IF (#CurrWeek = 1)
BEGIN SET #date = #currdate + 14 END
IF (#CurrWeek = 2)
BEGIN SET #date = #currdate + 7 END
IF (#CurrWeek = 3)
BEGIN SET #date = #currdate END
IF (#CurrWeek = 4)
BEGIN SET #date = #currdate - 7 END
IF (#CurrWeek = 5)
BEGIN SET #date = #currdate - 14 END
END
IF (#Week = 4)
BEGIN
IF (#CurrWeek = 1)
BEGIN SET #date = #currdate + 21 END
IF (#CurrWeek = 2)
BEGIN SET #date = #currdate + 14 END
IF (#CurrWeek = 3)
BEGIN SET #date = #currdate + 7 END
IF (#CurrWeek = 4)
BEGIN SET #date = #currdate END
IF (#CurrWeek = 5)
BEGIN SET #date = #currdate - 7 END
END
IF (#Week = 5)
BEGIN
IF (#CurrWeek = 1)
BEGIN SET #date = #currdate + 28 END
IF (#CurrWeek = 2)
BEGIN SET #date = #currdate + 21 END
IF (#CurrWeek = 3)
BEGIN SET #date = #currdate + 14 END
IF (#CurrWeek = 4)
BEGIN SET #date = #currdate + 7 END
IF (#CurrWeek = 5)
BEGIN SET #date = #currdate END
END
Select CONVERT(date, DATEADD(wk, DATEDIFF(wk, 0, #date), - 1)) as startdate,
CONVERT(date, DATEADD(wk, DATEDIFF(wk, 0, #date), 5)) as enddate
RETURN
I modified code given by Valex to get the exact output as I required.
CREATE PROCEDURE dbo.SPReturnStartEndDateOfSpecifiedWeek
#Week int,
#P_startdate DateTime OUTPUT,
#P_enddate DateTime OUTPUT
AS
/* SET NOCOUNT ON */
with C(i) as
(
select CAST((DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0)) as datetime) i
UNION ALL
select DATEADD (day,1,i) i from C
where DATEADD (day,1,i)<DATEADD(month,1,(DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0)))
),
C1 as
(
select DATEPART(WEEK,i)-DATEPART(WEEK,(DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0)))+1 WeekOfMonth,i from C
),
C2 as
(
select WeekOfMonth,min(i) StartDate, max(i) EndDate from C1 group by WeekOfMonth
)
Select #P_startdate = StartDate,
#P_enddate = EndDate
from C2
WHERE WeekOfMonth=#Week
RETURN
You can try this to get the start or end date for the week. Just provide a date for which you find the dates.
Logic is quite simple just get the start and end date of the week and then check if the start date is greater than the month date if so take the month date as the week start date else the start date of the week.
Fiddle a bit to get what you want
Here is the code:
DECLARE #date datetime
SET #date = '2013-01-30'
DECLARE #startdate datetime
DECLARE #enddate datetime
DECLARE #MonthStart datetime
Declare #MonthEnd datetime
SET #startdate = DATEADD(wk, DATEDIFF(wk, 6, #date), 6)
SET #enddate = DATEADD(dd,6, DATEADD(wk, DATEDIFF(wk, 6, #date), 6))
SET #monthStart = CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(#date)-1),#date),101)
SET #MonthEnd =CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,#date))),DATEADD(mm,1,#date)),101)
--select #startdate wstart,#MonthStart monthstart,#enddate wend,#MonthEnd monthend
select
[date] = #date
,[week] = DATEPART(wk,#date)
,[WeekStartDate] = Case
WHEN #startdate <= #MonthStart then #MonthStart else #startdate
END
,[WeekEndDate] = Case
WHEN #enddate > #MonthEnd then #MonthEnd else #enddate
END
see here:
Fiddle