How to create date table with given datetime range? - sql-server

I'm trying to create a table for calendar.But sql server stops at '2000-01-11 17:45'. How can i do create dates adding 15 minutes until 2050
Create Table Calendar
(id int IDENTITY(1,1) Primary key,CalendarDate DATETIME)
Declare #beginDate DATETIME, #endDate DATETIME
Select #beginDate = '2000-01-01 17:45', #endDate = '2050-01-01 09:00'
While #beginDate <= #endDate
Begin
Insert Into dbo.Calendar(CalendarDate)
Select
#beginDate As CalendarDate
Set #beginDate = DateAdd(MINUTE, 15, #beginDate)
End

Your current syntax suggest SQL Server, so i would try with recursive CTE :
with cte as (
select #beginDate as st
union all
select DATEADD(MINUTE, 15, st)
from cte
where st < #endDate
)
Insert Into dbo.Calendar(CalendarDate)
select st as CalendarDate
from cte
option (maxrecursion 0);

Related

Stored procedure to add 30 days using DATEDIFF within while loop condition in Date Dimension table

I want to add 30 consecutive days of data in my Date Dimension table using DATEDIFF() but I am getting blank result. Can you please help me correct the code below to get the desired result?
CREATE TABLE dbo.dateDimension (
DateKey INT NOT NULL
,DateValue DATE NOT NULL
,CYear SMALLINT NOT NULL
,CMonth TINYINT NOT NULL
,CONSTRAINT PK_DimDate PRIMARY KEY ( DateKey )
);
GO
CREATE PROC dbo.dateTest
#StartDate DATETIME
AS
WHILE (DATEDIFF(day, #StartDate, GETDATE()) <=30)
BEGIN
INSERT into dbo.dateDimension
SELECT CAST( YEAR(#StartDate) * 10000 + MONTH(#StartDate) * 100 + DAY(#StartDate) AS INT)
,#StartDate
,YEAR(#StartDate)
,MONTH(#StartDate)
SET #StartDate = DATEADD(d,1,#StartDate)
END;
GO
EXECUTE dbo.dateTest '2010-01-01'
SELECT * FROM dbo.dateDimension
The issue is that this logic:
DATEDIFF(day, #StartDate, GETDATE())
gives 3739 days with your current start date, so its never less than 30. Personally I would simply count it as follows:
DECLARE #StartDate DATETIME = '2010-01-01', #Count INT = 0;
WHILE #Count <= 30 BEGIN
INSERT into dbo.dateDimension
SELECT CAST( YEAR(#StartDate) * 10000 + MONTH(#StartDate) * 100 + DAY(#StartDate) AS INT)
, #StartDate
, YEAR(#StartDate)
, MONTH(#StartDate);
SET #StartDate = DATEADD(d,1,#StartDate);
set #Count = #Count + 1;
END;
SELECT *
FROM dbo.dateDimension;
If you are using SQL Server 2016 or above, this solution will not use a while loop, instead it uses a CTE to generate 30 rows numbered I to 30 and then uses the date to convert to yyyymmdd.
DECLARE #NUM_DAYS INT=30;
DECLARE #STARTDATE DATETIME='2020-01-01';
WITH CTE AS(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS SRL
FROM STRING_SPLIT(REPLICATE(',',#num_days-1), ',') AS A
)
INSERT INTO dbo.dateDimension
SELECT
CONVERT(INT, CONVERT(CHAR(8), DATEADD(DAY, SRL-1, #STARTDATE), 112))
, #STARTDATE
, YEAR(#STARTDATE)
, MONTH(#STARTDATE)
FROM CTE
SELECT * FROM dbo.dateDimension

Get monthly attendance for an employee

I have a query that a guy helped here in developing which gives fine result. I want to use this query in a function which later I want to use in a procedure.
CREATE FUNCTION [dbo].[fnGetWorkedDays] (#StartDate datetime, #EndDate datetime)
RETURNS int
AS
BEGIN
DECLARE #dateFrom datetime
DECLARE #dateTo datetime
SET #dateFrom = #StartDate
SET #dateTo = #EndDate
DECLARE #DAYSWORKED INT
SELECT #DAYSWORKED = (
SELECT EmpId, COUNT(*) as DaysWorked
FROM
(
SELECT DISTINCT EmpId,CAST(TimeIn AS DATE) AS [Date]
FROM myTable
WHERE TimeIn IS NOT NULL
AND CAST(TimeIn AS DATE) BETWEEN #StartDate AND #EndDate
)T
GROUP BY EmpId
ORDER BY EmpId)
RETURN ISNULL(#DAYSWORKED,0)
END
The very first error I am getting is that
Msg 1033, Level 15, State 1, Procedure fnGetWorkedDays, Line 24
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
I removed ORDER BY then I got another error says
Msg 116, Level 16, State 1, Procedure fnGetWorkedDays, Line 25
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
I suggest you to go though this to understand more on table valued functions vs scalar valued function Difference between scalar, table-valued, and aggregate functions in SQL server?
Regarding your scenario, you should be writing a table values function for this like following.
CREATE FUNCTION [dbo].[fnGetWorkedDays]
(
#StartDate AS DATETIME,
#EndDate datetime
)
RETURNS TABLE
AS
RETURN
SELECT EmpId, COUNT(*) as DaysWorked
FROM
(
SELECT DISTINCT EmpId,CAST(TimeIn AS DATE) AS [Date]
FROM myTable
WHERE TimeIn IS NOT NULL
AND CAST(TimeIn AS DATE) BETWEEN #StartDate AND #EndDate
)T
GROUP BY EmpId
To use the function you can write your queries like following.
DECLARE #StartDate datetime
DECLARE #EndDate datetime
SET #StartDate = '2018-01-01'
SET #EndDate = '2018-01-31'
select * from [dbo].[fnGetWorkedDays](#StartDate,#EndDate)
If you want this to work as a scalar value function, in that case you need to pass EmpId as parameter like following.
CREATE FUNCTION [dbo].[fnGetWorkedDaysEmpWise]
(
#StartDate AS DATETIME,
#EndDate datetime,
#EmpId INT
)
RETURNS INT
AS
BEGIN
DECLARE #RetunCount INT
SELECT #RetunCount = COUNT(DISTINCT CAST(TimeIn AS DATE))
FROM myTable
WHERE TimeIn IS NOT NULL
AND CAST(TimeIn AS DATE) BETWEEN #StartDate AND #EndDate
AND EmpID=#EmpId
RETURN #RetunCount
END
And you can use it directly in your select clause like following.
DECLARE #StartDate datetime
DECLARE #EndDate datetime
SET #StartDate = '2018-01-01'
SET #EndDate = '2018-01-31'
SELECT [dbo].[fnGetWorkedDaysEmpWise](#StartDate,#EndDate,1)
Is this what you are looking for .?
CREATE FUNCTION [dbo].[fnGetWorkedDays] (#StartDate datetime, #EndDate datetime)
RETURNS #DaysWorked TABLE
(
Empid Int,
DaysWorked Int
)
AS
BEGIN
insert into #DaysWorked (Empid,DaysWorked)
SELECT EmpId, COUNT(*) as DaysWorked
FROM
(
SELECT DISTINCT EmpId,CAST(TimeIn AS DATE) AS [Date]
FROM myTable
WHERE TimeIn IS NOT NULL
AND CAST(TimeIn AS DATE) BETWEEN #StartDate AND #EndDate
)T
GROUP BY EmpId
ORDER BY EmpId
RETURN
END
select * from [fnGetWorkedDays]('2018-01-01','2018-01-31')

Get dates between 2 dates with equal intervals

I have 2 dates 01/04/2017 and 30/04/2017. I want all the dates between these 2 dates with 7 days interval.
Expected Output :
01/04/2017
08/04/2017
15/04/2017
22/04/2017
29/04/2017
Please help!!
DECLARE #StartDate DATETIME,
#EndDate DATETIME
SELECT #StartDate = '2017-04-01',
#EndDate = '2017-04-30'
SELECT DATEADD(DAY, number*7, #StartDate)
FROM master.dbo.spt_values
WHERE type='P'
AND #EndDate >= DATEADD(DAY, number*7, #StartDate)
One method would be to use a Calendar table. Then return the results from there using the modulus to get the 7th rows:
WITH Dates AS(
SELECT *,
ROW_NUMBER() OVER (ORDER BY [date]) AS RN
FROM DateTable
WHERE [Date] BETWEEN '20170401' AND '20170430')
SELECT *
FROM Dates
WHERE (RN - 1) % 7 = 0;
I've used this solution, as from your post you imply that you might supply any date range, and that the 1st day may not necessarily be a Monday (or other specific day).
Try this
DECLARE #STRT DATETIME='04/01/2017',#END DATETIME ='04/30/2017'
;WITH CTE
AS
(
SELECT
MyDate = CAST(#STRT AS DATETIME)
UNION ALL
SELECT
MyDate = CAST(MyDate AS DATETIME)+7
FROM CTE
WHERE CAST(MyDate AS DATETIME)+7 < CAST(#END AS DATETIME)
)
SELECT
*
FROM CTE
result
Declare #StartDate DATE=CONVERT(DATE,'01/04/2017',104),#EndDate DATE=CONVERT(DATE,'01/12/2017',104)
Declare #String NVARCHAR(MAX)=''
WHILE (#StartDate<=#EndDate AND DATEDIFF(wk,#StartDate,#EndDate)>=0)
BEGIN
SET #String=#String+CONVERT(NVARCHAR(100),#StartDate)+CHAR(10)+CHAR(13)
SET #StartDate=DATEADD(d,7,#StartDate)
END
PRINT #String
GO

How to declare dates in SQL multiple value

I am trying to create my SQL syntax so that we can have versatile input. I figured out how to do it for one set date and it worked.
my syn is:
DECLARE #MyDay AS VARCHAR(50);
DECLARE #NextDay AS VARCHAR(50);
SET #MyDay = '8/30/2016';
SET #NextDay = DATEADD(d, 1, #MyDay);
However, I'm stuck with how to do it for multiple dates. Ideally I would like to put in a range of date, and from that it will scan the records, i.e. set range between oct 1st and oct 5th.
I'm using SQL Server Management Studio 2008
If you just want a series of days and next days between 8/30/16 and 9/5/16, you can use a derive table method like below.
declare #n int;
declare #StartDate datetime, #EndDate datetime;
set #n = 5;
set #StartDate = '20160830';
set #EndDate = dateadd(day, #n, #StartDate);
select cast(dateadd(day, number, #StartDate) as date) as MyDate,
cast(dateadd(day, number + 1, #StartDate) as date) as MyNextDate
from
(select distinct number from master.dbo.spt_values
where name is null
) n
where dateadd(day, number, #StartDate) < #EndDate;
Alternately you can use a temp table, table variable to store your dates, or a cte as well.
A recursive cte imlementation example is given below. Please note you would want to set MAXRECURSION option if you have a long date range as default for max recursion is 100.
declare #n int;
declare #StartDate datetime, #EndDate datetime;
set #n = 5;
set #StartDate = '20160830';
set #EndDate = dateadd(day, #n, #StartDate);
;with DateSeq as
(
select cast(#StartDate as date) as MyDate
union all
select dateadd(day , 1, MyDate) AS MyDate
from DateSeq where dateadd (day, 1, MyDate) < #EndDate
)
select MyDate, dateadd(day , 1, MyDate) AS NextDate
from DateSeq;
A temp table implementation example is as below.
declare #MyDateRange table(MyDate date);
Insert into #MyDateRange values('8/30/2016')
Insert into #MyDateRange values('9/1/2016')
Insert into #MyDateRange values('9/2/2016')
Insert into #MyDateRange values('9/3/2016')
Insert into #MyDateRange values('9/4/2016')
select MyDate, dateadd(day, 1, MyDate) as NextDate from #MyDateRange

SQL server SP : #Param 's with sometime NULL values

I am very new to SQL Server Stored Procedures,
I am trying to create a SP that will give return a list of records in a table by filter via StartDate and EndDate , but there will be 'View All' Option so sometime those #Param might not contain any values.
Currently my SP is Like
CREATE PROCEDURE [dbo].[spGetBonusRun]
(
#StartDate as DATETIME,
#EndDate as DATETIME
)
AS
SELECT [Id]
,[StartDateTime]
,[EndDate]
,[Status]
FROM [Valt].[dbo].[BonusRun]
WHERE StartDateTime <= #StartDate AND EndDate >= #EndDate
How to active that ?
Try this:
WHERE (StartDateTime <= #StartDate OR #StartDate IS NULL) AND (EndDate >= #EndDate OR #EndDate IS NULL)
Hope it helps.
/Klaus
You can try something like this
CREATE PROCEDURE [dbo].[spGetBonusRun]
(
#StartDate as DATETIME,
#EndDate as DATETIME
)
AS
SELECT [Id]
,[StartDateTime]
,[EndDate]
,[Status]
FROM [Valt].[dbo].[BonusRun]
WHERE StartDateTime <= ISNULL(#StartDate, StartDateTime)
AND EndDate >= ISNULL(#EndDate, EndDate)
Note the use of ISNULL

Resources