T-SQL Case statement in Where clause problem - tsql

I'm trying to get a WHERE clause working so,
when #Status is 2 then find where the UnitBookedDate is between the StartDate and EndDate
when #Status is 4 then find where the InstallDate is between the StartDate and EndDate
when #Status is null then find where the UnitBookedDate OR the InstallDate is between the StartDate and EndDate
I'm thinking maybe the CASE statement won't work for what I need.
WHERE
TMFT.IsUnit = 1 AND
I.InstallTypeId < 3 AND
CASE
WHEN #Status = 2 THEN I.UnitBookedDate
WHEN #Status = 4 then TMF.InstallDate
WHEN #Status IS NULL THEN I.UnitBookedDate --or TMF.InstallDate
END
BETWEEN #StartDate AND #EndDate

Have you tried it like this...
WHERE
TMFT.IsUnit = 1 AND
I.InstallTypeId < 3 AND
(#Status = 2 AND I.UnitBookedDate BETWEEN #StartDate AND #EndDate)
OR (#Status = 4 AND TMF.InstallDate BETWEEN #StartDate AND #EndDate)
OR #Status IS NULL AND (I.UnitBookedDate BETWEEN #StartDate AND #EndDate OR TMF.InstallDate BETWEEN #StartDate AND #EndDate)

Related

Calculating the business differences in sql in the form of day, hours and minutes - SQL Server

With the below function I getting the result as 00:09:10 however I want the result to be as 01:00:10.
So hours is considered as considered as 1 day.
Example if hours is 30 then it will be 03:03:00 and so on
fn_GetHolidayMinutes : Get holiday in minutes between two dates and country
CREATE FUNCTION [dbo].[fn_GetHolidayMinutes]
(#StartDate DATETIME,
#EndDate DATETIME,
#CountryId BIGINT)
RETURNS BIGINT
AS
BEGIN
DECLARE #OUTPUT BIGINT;
DECLARE #HolidayList TABLE (HolidaysDate DATE)
-- Create Table #HolidayList
-- (
-- HolidaysDate date
-- )
DECLARE #Date1 DATE, #Date2 DATE
DECLARE holiday_cursor CURSOR FOR
SELECT StartDate,EndDate
FROM Holidays
WHERE IsActive = 1
AND CountryId = #CountryId
AND ((StartDate BETWEEN #StartDate AND #EndDate) OR
(EndDate BETWEEN #StartDate AND #EndDate))
OPEN HOLIDAY_CURSOR
FETCH NEXT FROM HOLIDAY_CURSOR INTO #Date1, #Date2
WHILE ##FETCH_STATUS = 0
BEGIN
--INSERT INTO #HolidayList
INSERT INTO #HolidayList
SELECT DATEADD(DAY, number, #Date1) [Date]
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(DAY, number, #Date1) <= #Date2
FETCH NEXT FROM HOLIDAY_CURSOR INTO #Date1, #Date2
END
CLOSE HOLIDAY_CURSOR;
DEALLOCATE HOLIDAY_CURSOR;
(SELECT #OUTPUT= COUNT(DISTINCT HolidaysDate)
FROM #HolidayList
WHERE HolidaysDate BETWEEN #StartDate AND #EndDate
AND DATEPART(dw, HolidaysDate) NOT IN (SELECT DISTINCT number
FROM master..spt_values
WHERE number BETWEEN 1 and 7
AND number NOT IN (SELECT WorkingDay
FROM WorkingDays
WHERE CountryId = #CountryId AND IsActive = 1)
))
---print #OUTPUT; --this will give in days
--get the output in minutes
RETURN #OUTPUT * (SELECT TOP 1 STUFF(WorkingHours, 2, 2, '')
FROM dbo.WorkingDays
WHERE CountryId = #CountryId) * 60;
END
fn_GetWorkingDayMinuts :
CREATE FUNCTION [dbo].[fn_GetWorkingDayMinuts]
(#StartDate DATETIME,
#EndDate DATETIME,
#CountryId BIGINT)
--RETURNS BIGINT
RETURNS VARCHAR(250)
AS
BEGIN
DECLARE #Temp BIGINT
SET #Temp = 0
DECLARE #FirstDay DATE
SET #FirstDay = CONVERT(DATE, #StartDate, 112)
DECLARE #LastDay DATE
SET #LastDay = CONVERT(DATE, #EndDate, 112)
DECLARE #StartTime TIME
SET #StartTime = CONVERT(TIME, #StartDate)
DECLARE #FinishTime TIME
SET #FinishTime = CONVERT(TIME, #EndDate)
DECLARE #WorkStart TIME
SET #WorkStart = (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
WorkStartTime FROM WorkingDays WHERE CountryId=#CountryId), 120)))
DECLARE #WorkFinish TIME
SET #WorkFinish = (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
WorkEndTime FROM WorkingDays WHERE CountryId=#CountryId), 120)))
DECLARE #DailyWorkTime BIGINT
SET #DailyWorkTime = DATEDIFF(MINUTE, #WorkStart, #WorkFinish)
IF (#StartTime<#WorkStart)
BEGIN
SET #StartTime = #WorkStart
END
IF (#FinishTime>#WorkFinish)
BEGIN
SET #FinishTime=#WorkFinish
END
IF (#FinishTime<#WorkStart)
BEGIN
SET #FinishTime=#WorkStart
END
IF (#StartTime>#WorkFinish)
BEGIN
SET #StartTime = #WorkFinish
END
DECLARE #CurrentDate DATE
SET #CurrentDate = #FirstDay
DECLARE #LastDate DATE
SET #LastDate = #LastDay
WHILE(#CurrentDate<=#LastDate)
BEGIN
--IF (DATEPART(dw, #CurrentDate)!=1 AND DATEPART(dw, #CurrentDate)!=7)
IF(DATEPART(dw, #CurrentDate) IN (SELECT distinct number FROM master..spt_values WHERE number BETWEEN 1 and 7
AND number NOT IN (SELECT
WorkingDay FROM WorkingDays where CountryId=#CountryId and IsActive=1)
))
BEGIN
IF (#CurrentDate!=#FirstDay) AND (#CurrentDate!=#LastDay)
BEGIN
SET #Temp = #Temp + #DailyWorkTime
END
--IF it starts at startdate and it finishes not this date find diff between work finish and start as minutes
ELSE IF (#CurrentDate=#FirstDay) AND (#CurrentDate!=#LastDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #StartTime, #WorkFinish)
END
ELSE IF (#CurrentDate!=#FirstDay) AND (#CurrentDate=#LastDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #WorkStart, #FinishTime)
END
--IF it starts and finishes in the same date
ELSE IF (#CurrentDate=#FirstDay) AND (#CurrentDate=#LastDay)
BEGIN
SET #Temp = DATEDIFF(MINUTE, #StartTime, #FinishTime)
END
END
SET #CurrentDate = DATEADD(day, 1, #CurrentDate)
END
-- Return the result of the function
IF #Temp<0
BEGIN
SET #Temp=0
END
--RETURN #Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0, DATEDIFF(dd, 0, #StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
#EndDate)),#CountryId))
--RETURN #Temp
DECLARE #theMinutes INT
DECLARE #Result VARCHAR(250)
SET #theMinutes = #Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0,
DATEDIFF(dd, 0, #StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
#EndDate)),#CountryId))
--SET #Result= concat((#theMinutes / 540),':' , (#theMinutes % 540) /
60, ':', (#theMinutes % 60))
SET #Result= concat((#theMinutes / ((SELECT TOP 1
STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
CountryId=#CountryId) * 60)),':' , (#theMinutes % ((SELECT TOP 1
STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
CountryId=#CountryId) * 60)) / 60, ':', (#theMinutes % 60))
RETURN #Result
END
So where to modify to the result as
BUSINESS HOURS CREATE DATE & TIME FIRST APPLY (DATE & TIME) TAT TIME CALCULATION RESULT
08h00-17h00: 9hrs/day 12-FEB-19 14:20 13-FEB-19 14:30 00:02:40 + 00:06:30 = 00:09:10 01:00:10

Find the missing hour with Lag analytic function

I have to find the missing hour in my table , for frequency = 1 I have to find a record per hour, if it's not the case, I have to display the missing hour.
here's my code
declare #StartDate datetime declare #EndDate datetime declare #now datetime set #now = getdate() set #StartDate = dateadd(day,-30,#now) set #EndDate = dateadd(day,-2,#now) Select Flow.Id,Flow.ComponentId, Frequency.Name frequencyName, Flow.MeasurementDate as MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) LagValue, abs( DATEDIFF (hour, MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) ) ) DifferenceDate , (CASE WHEN DATEDIFF (hour, MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) ) > '1' THEN 'Yes' ELSE 'No' END) AS Gap into #tab1 FROM Data.dbo.Flow inner join Data.dbo.Component on flow.ComponentId = Component.Id inner join Data.dbo.Frequency on Flow.Frequency = Frequency.Id Where flow.LoaderCode='TOT' and Flow.Frequency='1' and ScheduledVolume IS NOT NULL and MeasurementDate between #StartDate and #EndDate --and DATEDIFF (hour, MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) ) >1 Group By Frequency.Name, Flow.MeasurementDate, Flow.ComponentId select * from #tab1
--if i right understood then try this
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
DECLARE #now DATETIME
IF OBJECT_ID('Tempdb..#tab1') IS NOT NULL
BEGIN
DROP TABLE #tab1
END
SET #now = GETDATE()
SET #StartDate = GETDATE() - 30
SET #EndDate = GETDATE() - 2
SELECT Flow.Id ,
Flow.ComponentId ,
Frequency.Name AS frequencyName ,
CONVERT(DATE, Flow.MeasurementDate) AS [Measurement Date] ,
DATEPART(HOUR, Flow.MeasurementDate) AS [Measurement Hour] ,
COALESCE(LAG(DATEPART(HOUR, Flow.MeasurementDate)) OVER ( PARTITION BY CONVERT(DATE, MeasurementDate) ORDER BY DATEPART(HOUR,
MeasurementDate) ),
0) AS [Measurement Previous Hour]
INTO #tab1
FROM Data.dbo.Flow
INNER JOIN Data.dbo.Component ON Flow.ComponentId = Component.Id
INNER JOIN Data.dbo.Frequency ON Flow.Frequency = Frequency.Id
WHERE Flow.LoaderCode = 'TOT'
AND Flow.Frequency = '1'
AND ScheduledVolume IS NOT NULL
AND CONVERT(DATE, MeasurementDate) BETWEEN CONVERT(DATE, #StartDate)
AND CONVERT(DATE, #EndDate)
SELECT T.* ,
CASE WHEN ( T.[Measurement Hour] - T.[Measurement Previous Hour] ) > 1
THEN ( T.[Measurement Hour] - T.[Measurement Previous Hour] - 1 )
ELSE 0
END AS [Missing Hours]
FROM #tab1a AS T
WHERE ( T.[Measurement Hour] - T.[Measurement Previous Hour] ) > 1

tsql select query by time from and time to

I need to have a select query where the query is filtered by time format like this.
From: 7:00 AM
To: 8:00 AM
for example:
DECLARE #TimeFrom varchar(7)
DECLARE #TimeTo varchar(7)
DECLARE #StartDate varchar(10)
DECLARE #EndDate varchar(10)
SET #TimeFrom = '7:00 AM'
SET #TimeTo = '8:00 AM'
SET #StartDate = '05/07/2014'
SET #EndDate = '05/07/2014'
SELECT *
FROM [Call]
WHERE LTRIM(RIGHT(CONVERT(VARCHAR(20),StartTime,100),7)) BETWEEN #TimeFrom AND #TimeTo
and CONVERT(VARCHAR, StartTime, 101) = '05/07/2014'
AND SubDispositionID LIKE ('SA%')
ORDER BY StartTime ASC
The problem with this query is I am also getting data from 7:00 PM to 8:00 PM.
It is because you compare STRINGS so 7:00 PM is between 7:00 AM AND 8:00 AM
I think you should avoid 'AM\PM' and use 24h notation:
SET #TimeFrom = '07:00'
SET #TimeTo = '08:00'
....
WHERE CONVERT(VARCHAR(5),StartTime,108) BETWEEN #TimeFrom AND #TimeTo
Here is conversion to VARCHAR(5) to cut seconds from time string.
DECLARE #TimeFrom varchar(7)
DECLARE #TimeTo varchar(7)
DECLARE #StartDate varchar(10)
DECLARE #EndDate varchar(10)
SET #TimeFrom = '7:00 AM'
SET #TimeTo = '8:00 AM'
SET #StartDate = '05/07/2014'
SET #EndDate = '05/07/2014'
SELECT *
FROM [Call]
WHERE CONVERT(varchar, StartTime, 108) BETWEEN (select CONVERT(varchar(8), cast(#TimeFrom as datetime), 108))
AND (select convert(varchar(8), cast(#TimeTo as datetime), 108))
and CONVERT(VARCHAR, StartTime, 101) = '05/07/2014'
AND SubDispositionID LIKE ('SA%')
ORDER BY StartTime ASC

Optional parameters and date index

I'm playing around with two very simple queries. There is a non-clustered index with StartDate and EndDate, as well as Id as an included column.
DECLARE #startDate DATETIME, #endDate DATETIME
SELECT #startDate = '4/1/2011', #endDate = '5/1/2011'
-- Does Index Scan (slow)
SELECT Id
FROM dbo.Table
WHERE
(#startDate IS NULL OR StartDate >= #startDate) AND
(#endDate IS NULL OR EndDate < #endDate)
-- Does Index Seek (fast)
SELECT Id
FROM dbo.Table
WHERE
(StartDate >= #startDate) AND
(EndDate < #endDate)
Is there any way to rearrange, pre-calculate, or otherwise change the query to have an index seek occur in the first example?
Edit: I know this is a very basic indexing problem, but I haven't found a good solution yet. Note that I am declaring the variables, but those would be parameters in an sproc.
What about the following?
DECLARE #startDate DATETIME, #endDate DATETIME
SELECT #startDate = '4/1/2011', #endDate = '5/1/2011'
SELECT Id
FROM dbo.Table
WHERE
StartDate >= ISNULL(#startDate, '1/1/1753')
AND
EndDate < ISNULL(#endDate, '12/31/9999')
This code is probably broken if you have an end date of 12/31/9999 in your table that you actually want returned from your result set, but how often does that happen?

execute programmatically stored procedures with different parameter values

I have stored procedure
getList(#date datetime)
how programmatically execute stored procedure for differend datetime values.
datetime each month for 3 years.
You can try something like this
DECLARE #StartDate DATETIME,
#EndDate DATETIME
SELECT #StartDate = '01 Jan 2005',
#EndDate = '31 Dec 2007'
WHILE #StartDate <= #EndDate
BEGIN
PRINT #StartDate
EXEC getList(#StartDate)
SET #StartDate = DATEADD(mm, 1, #StartDate)
END
Just add one month to the current date?
DATEADD(month, 1, GETDATE())