Creating a dynamic date range in SQL - sql

How can I construct a SQL statement that will always return a start date of July 1 of the previous year, and an end date of June 30 of the current year based on GETDATE()? Right now I have
Dateadd(yy, Datediff(yy,1,GETDATE())-1,0) AS StartDate,
DateAdd(dd,-1,Dateadd(yy, Datediff(yy,0,GETDATE()),0)) AS EndDate
which will return January 1, 2012 and December 31, 2013 respectively..

You could just add another DATEADD() to your current script:
SELECT DATEADD(month,6,DATEADD(yy, DATEDIFF(yy,1,GETDATE())-1,0)) AS StartDate
,DATEADD(month,6,DATEADD(dd,-1,DATEADD(yy, DATEDIFF(yy,0,GETDATE()),0))) AS EndDate

This seems like an odd request. One way of doing it is by constructing date strings and parsing them:
select cast(cast(year(GETDATE()) - 1 as varchar(255))+'-07-01' as DATE) as StartDate,
cast(cast(year(GETDATE()) as varchar(255))+'-06-30' as DATE) as EndDate
This constructs the strings in the format '2013-06-30', which will be interpreted correctly on for most SQL Server date settings.
I believe (recalling something Aaron Bertrand wrote) that leaving out the hyphens always works:
select cast(cast(year(GETDATE()) - 1 as varchar(255))+'0701' as DATE) as StartDate,
cast(cast(year(GETDATE()) as varchar(255))+'0630' as DATE) as EndDate
I, as a human, just much prefer having the hyphens.

I've been using this CTE for dynamic fiscal year ranges based on the current date. It returns the start and end dates for the current fiscal year based on the current date.
WITH FYDates AS (
SELECT
CASE
WHEN MONTH(GETDATE()) IN (1, 2, 3, 4, 5, 6)
THEN CAST(CAST(YEAR(GETDATE()) - 1 AS VARCHAR) + '/07/01' AS DATE)
ELSE CAST(CAST(YEAR(GETDATE()) AS VARCHAR) + '/07/01' AS DATE) END AS FYStartDate,
CASE
WHEN MONTH(GETDATE()) IN (1, 2, 3, 4, 5, 6)
THEN CAST(CAST(YEAR(GETDATE()) AS VARCHAR) + '/06/30' AS DATE)
ELSE CAST(CAST(YEAR(GETDATE()) + 1 AS VARCHAR) + '/06/30' AS DATE) END AS FYEndDate
),
You can also create this as a view to reference that when needed.

This should work for you:
SELECT CAST('7/1/' + CAST(DATEPART(yy, Dateadd(yy, Datediff(yy,1,GETDATE())-1,0)) as varchar) as varchar) as startdate,
CAST('6/30/' + CAST(DATEPART(yy, Dateadd(yy, Datediff(yy,0,GETDATE()),0)) as varchar) as varchar) as enddate

Related

T-SQL Dynamic date range in WHERE clause (Last fiscal year + year to date)

I'm using the following WHERE clause to only load records from the last fiscal year plus a year to date.
Running without the WHERE clause, it takes 30seconds for 1mil records. With the WHERE clause, I had to stop it after 2hours.
Can you please share your thoughts
WHERE
([schema].[table].[DATE] >= DATEADD
(yy, - 1, DATEADD
(MONTH,(MONTH(GETDATE()) - 1) / 6 * 12 - 6,
CAST(CAST(YEAR(GETDATE()) AS VARCHAR) AS DATETIME)
)
)
)
Declare #PastFiscalYear Date
Set #PastFiscalYear= DATEADD(yy, - 1, DATEADD(MONTH,(MONTH(GETDATE()) - 1) / 6 * 12 - 6,CAST(CAST(YEAR(GETDATE()) AS VARCHAR) AS DATETIME)))
WHERE
([schema].[table].[DATE] >= #PastFiscalYear )
Can you try this
This will bring back data since the previous fiscal year start date. Just change the -3 to what ever your FY offset is. -3 is for October.
[schema].[table].[DATE] >= DATEADD(mm,-3,DATEADD(YEAR, DATEDIFF(YEAR, 0, DATEADD(YEAR, -1, GETDATE())), 0))

How can I use GETDATE() to get month and year from the past month?

How can I get it to one statement that can get me
last month and this year?
I have a INSERT INTO and in a column report_date [datetime]
insert into table_a (report_date) values ( ??);
i want to show this past month and year,
So for example today is 4/21/2014
so it would show 3/2014 in the column
If today was MAY 1 2014 , it would show 4/2014?
Is this possible or does it have to have a day?
You're looking for the DATEADD function:
SELECT DATEPART(month, DATEADD(month, -1, GETDATE()), DATEPART(year, DATEADD(month, -1, GETDATE())
If you are trying to get 'last month' with 'this year' you could do:
SELECT CAST(
CAST(YEAR(GETDATE()) AS VARCHAR) + '-' +
CAST(MONTH(GETDATE())-1 AS VARCHAR) + '-' +
CAST(DAY(GETDATE()) AS VARCHAR)
AS DATETIME)
But then in JAN 2015, it would return DEC 2015.
If you just want last month, use the 'DATEADD' function.
SELECT DATEADD(MONTH, -1, GETDATE())

Generate a day date according to existing month+year+daydiff

I'm using SQL Server 2008.
I got a table with these 5 columns:
StartMonth, StartYear, EndMonth, EndYear, DaysBetween
I don't have the day of these dates and that's what I?m trying to generate.
For example:
12 2008 1 2009 8
I want to create a random date (start date and end date , format as dd/mm/yyyy) which will include the day and will make scene upon the data I have under days between
E.g., if I know that I got 8 days (DaysBetween) and the startmonth is 12, the date must be
from 24/12/2008 cause if I add 8 days I get the EndMonth (1/2009)
If I would choose the date 2/12/2008 I would get 10/12/2008 and its not good cause the month is still 12.... and I need 1 (2009)
How can I generate valid dates ?
Something like this?
WITH N(n) AS (
SELECT a*6+b FROM
(VALUES(0),(1),(2),(3),(4),(5))a(a),
(VALUES(1),(2),(3),(4),(5),(6))b(b)
), T(StartMonth,StartYear,EndMonth,EndYear,DaysBetween) AS (
SELECT 12, 2008, 1, 2009, 8
)
SELECT *
FROM (
SELECT *, DATEADD (dd, -n, DATEADD (mm, StartMonth, DATEADD (yy, StartYear - 1900, '19000101'))) AS dt
FROM T
INNER JOIN N ON DaysBetween >= n
) T
WHERE MONTH (dt) = StartMonth
AND YEAR (dt) = StartYear
AND MONTH (DATEADD (dd, DaysBetween, dt)) = EndMonth
AND YEAR (DATEADD (dd, DaysBetween, dt)) = EndYear
Here is a sample:
WITH CTE_Start AS
(
SELECT DATEADD(dd,-(ABS(CHECKSUM(NewId())) % DaysBetween+1),dateadd(mm, (EndYear - 1900) * 12 + EndMonth - 1,0)) StartDate, DaysBetween
FROM dbo.This5Columns
)
SELECT StartDate, DATEADD(dd,DaysBetween,StartDate) AS EndDate
FROM CTE_Start
ABS(CHECKSUM(NewId())) % DaysBetween+1
is used to get random number of days between 1 and DaysBetween,
dateadd(mm, (EndYear - 1900) * 12 + EndMonth - 1,0)
Gets the first date of end month (earliest possible end date)
Then you subtract the two to get your StartDate, and add DaysBetween again to get the EndDate
SQLFiddle DEMO
You need to parts to solve this:
Create a random value between 1 and the DaysBetween
Use the DateAdd function to pick a date X days before the first of the next month (X being the value from the previous part).
To create a random value try something like this:
SELECT Cast(( DAYSBETWEEN ) * Rand(Cast(Newid() AS VARBINARY)) + 1
AS
TINYINT) AS 'randomNumber'
FROM TABLE
Then add the dateadd function:
SELECT Dateadd(DD, Cast(( DAYSBETWEEN ) * Rand(Cast(Newid() AS
VARBINARY))
+ 1 AS
TINYINT), Dateadd(MONTH, 1,
Cast(
Cast(STARTMONT AS VARCHAR(2)) + '-01-'
+ Cast(#StartYear AS VARCHAR(4)) AS DATE)))
FROM TABLE

SQL Server 2008 select data only between month and year

I would like select data between two date, without day
An input example:
start month: 9 , start year: 2011
end month: 3, end year: 2012
I think that there are two way to do this.
The first is convert start month and start year to date like 2011-09-01 and convert last date to 2012-03-31, but this requires calculation of the last day of end month. Obtained these date we can use a BEETWEN function for the WHERE clause (but, is the CONVERT function reliable?)
The second solution is to use the DATEPART function like in the following code:
I try to explain: if end year is equal to the initial year, then month must be between the start and end months; else if the final months is greater than the initial years if different from the initial and final year, I take everything in between; else if the final year, the month must be less than or equal to the final month, if the initial year, month must be greater than or equal to the final month
Can you help me do this in the best way? Is correct, the solution I adopted?
declare #IndDebitoCredito bit,#ProgTributo int,#mi as integer,#ai as integer,#mf as integer,#af as integer,#IDAnagrafica varchar(5)
select #mi = 01,#ai = 2011,#mf = 12,#af = 2011,#IDAnagrafica = 'DELEL',#IndDebitoCredito = 1
select distinct rrd.IDTributo
from TBWH_Delega d
--inner join TBWH_SezioneDelega sd on d.IDDelega = sd.IDDelega
inner join TBWH_Rigo rd on rd.IDDelega = d.IDDelega
inner join TBWH_RataRigo rrd on rrd.IDRigo = rd.IDRigo
where
(
DATEPART(MM,d.DataDelega)<=#mf and
DATEPART(MM,d.DataDelega)>=#mi and
DATEPART(YYYY,d.DataDelega)=#ai and
#af = #ai
)
OR
(
--anno finale magg. anno iniziale
#af > #ai AND
(
( -- delega nell'intervallo
DATEPART(YYYY,d.DataDelega)<#af AND
DATEPART(YYYY,d.DataDelega)>#ai
-- DATEPART(MM,d.DataDelega)>=#mi
)
OR
( -- delega limite destro
DATEPART(YYYY,d.DataDelega)=#af AND
DATEPART(MM,d.DataDelega)<=#mf
)
OR
( -- delega limite sinistro
DATEPART(YYYY,d.DataDelega)=#ai AND
DATEPART(MM,d.DataDelega)>=#mi
)
)
)
GO
Your first solution is almost there, but is more complicated than it needs to be and won't work anyway. It will miss out any rows from the last day of the end month.
You can add one month to the end month and then use BETWEEN on the first of each month. eg.
start month: 9 , start year: 2011
end month: 3, end year: 2012
BETWEEN '2011-09-01' AND '2012-04-01'
or, as JNK points out, this will be better:
DataDelega >= '2011-09-01' AND DataDelega < '2012-04-01'
You'll need to add in some logic to deal with the end month being December, but this looks like the simplest way of doing it.
You are WAY overcomplicating this. You really only need two comparisons:
Is the month and year after or equal to the initial value?
Is the month and year before or equal to the final value?
Try:
SELECT *
FROM MyTable
WHERE Datefield BETWEEN
CAST(#mi as varchar) + '/1/' + CAST(#ai as varchar)
-- first of first month
AND
DATEADD(DAY, -1, (DATEADD(Month, + 1, (CAST(#mf as varchar) + '/1/' + CAST(#af as varchar)))))
-- Last day or final month
SELECT *
FROM Table
WHERE DateField
BETWEEN CONVERT(DATE, CONVERT(CHAR(4), #ai) + RIGHT('00' + CONVERT(VARCHAR(2), #mi), 2) + '01', 112)
AND DATEADD(DD, -1, DATEADD(MM, 1, CONVERT(DATE, CONVERT(CHAR(4), #af) + RIGHT('00' + CONVERT(VARCHAR(2), #mf), 2) + '01', 112)))
Avoid using expressions on the DateField columns, as it makes query not SARGable.
I would use:
WHERE DateToCheck >= --- first day of StartMonth
DATEADD( mm, #StartMonth-1,
DATEADD( yy, #StartYear-2000, '2000-01-01')
)
AND DateToCheck < --- first day of next month (after EndMonth)
DATEADD( mm, #EndMonth,
DATEADD( yy, #EndYear-2000, '2000-01-01')
)
DECLARE #mi INT
, #ai INT
, #mf INT
, #af INT
SELECT #mi = 01
, #ai = 2011
, #mf = 12
, #af = 2011
--local variables to hold dates
DECLARE #i DATETIME
, #f DATETIME
--build strings to represent dates in YYYYMMDD format
--add a month to the #f date
SELECT #i = CONVERT(VARCHAR(4), #ai) + RIGHT('0' + CONVERT(VARCHAR(2), #mi),
2) + '01'
, #f = DATEADD(month, 1,
CONVERT(VARCHAR(4), #af) + RIGHT('0'
+ CONVERT(VARCHAR(2), #mf),
2) + '01')
--select data where date >= #i, and < #f
SELECT *
FROM MyTable
WHERE DateField >= #i
AND DateField < #f

SQL: extract date from string

There is a text field called myDate. This field can contain either 1) 'Fiscal year ending someDate' or 2) 'dateA to 'dateB'.
In situation 1), I want to set the field date1 = to someDate.
In situation 2), I want to set the field date1 = dateA and the field date2 = dateB.
All the dates (someDate, dateA, dateB) can be written as 1/1/2000, Jan 1, 2000, or January 1, 2000.
How do I go about extracting the dates from myDate and inserting them into the correct fields?
This doesn't look complicated enough to need a "proper" regular expression. Those textual dates can be parsed directly into a DATETIME type by SQL without any mucking around, as you can see by running this query:
SELECT CAST('1/1/2000' AS DATETIME), CAST('January 1, 2000' AS DATETIME), CAST('Jan 1, 2000' AS DATETIME)
To get -1 year and +1 day, just use DATEADD, e.g.
SELECT DATEADD(dd, 1, DATEADD(yy, -1, 'January 1 2000'))
...so, all you really need to do is cope with your two different cases and grab the dates out. So, something like:
SELECT
CASE
WHEN myDate LIKE 'fiscal year ending %' THEN CAST(DATEADD(dd, 1, DATEADD(yy, -1, REPLACE(myDate, 'fiscal year ending ', ''))) AS DATETIME)
ELSE CAST(LEFT(myDate, PATINDEX('% to %', myDate)) AS DATETIME)
END 'FromDate',
CASE
WHEN myDate LIKE 'fiscal year ending %' THEN CAST(REPLACE(myDate, 'fiscal year ending ', '') AS DATETIME)
ELSE CAST(SUBSTRING(myDate, PATINDEX('% to %', myDate) + 4, 100) AS DATETIME)
END 'ToDate'
FROM
...whatever
...should do the trick. I've not really tested that, but hopefully it'll give you enough of an idea to see what I'm getting at.
Note that some of the results will probably depend on the language settings of your server/database. For example, while 1/1/2000 is always going to be 1 Jan, is 3/4/2000 the third of April, or the fourth of March?