I want to run a query on a specific date range for my company's fiscal year, which ends in October.
The query needs to run from October 1 of the last year through the current date, but if the current year gets past October, then it needs to switch over to October of this year.
So: currently it would be October 1, 2013 to July 16, 2014.
Starting on October 2, 2014 it will be October 2, 2014 to October 2, 2014.
I could simply go in and change the SQL every October, but I figured there was an easier way to do this with a logic statement.
Thanks!
Do you want something like this:
SELECT
<your_column_list>
FROM TABLE
WHERE
date_col >= CASE
WHEN MONTH(GETDATE()) < 10 THEN CAST(('1.10.' + CAST(YEAR(GETDATE()) - 1 as CHAR(4)) AS DATETIME)
ELSE GETDATE()
END
AND
date_col < CASE
WHEN MONTH(GETDATE()) < 10 THEN GETDATE()
ELSE
CAST(('1.10.' + CAST(YEAR(GETDATE()) + 1 as CHAR(4)) AS DATETIME)
END
I'm not sure about the exact dates, i don't get the october 2nd part. You will have to adjust the date format as well. I used dd.mm.yyyy on your system it might be different.
So this should be giving the desired results.
DECLARE #startDate DATETIME,
#endDate DATETIME,
#today DATETIME;
BEGIN
SET #today = CONVERT(DATETIME, '03/1/14');
SELECT #startDate = CASE
WHEN MONTH(#today) < 10 THEN '10/01/' + LTRIM(STR(YEAR(DATEADD(YEAR, -1, #today))))
WHEN MONTH(#today) = 10
AND MONTH(#today) = 1 THEN '10/01/' + LTRIM(STR(YEAR(DATEADD(YEAR, -1, #today))))
WHEN MONTH(#today) = 10
AND MONTH(#today) > 1 THEN '10/01/' + LTRIM(STR(YEAR(#today)))
WHEN MONTH(#today) > 10 THEN '10/01/' + LTRIM(STR(YEAR(#today)))
ELSE '1/1/2000'
END,
#endDate = GETDATE();
SELECT #startDate, #endDate;
END;
Related
First Day of financial year is April 1st.
T-SQL Query to return April 1st for the getdate()
Financial Year: April 1st to March 31st
Try this:
select DATEFROMPARTS(Yr, 4, 1) [start], DATEFROMPARTS(Yr + 1, 3, 31) [end] from
(select case when DATEPART(month, getdate()) < 4 then DATEPART(year, getdate()) - 1 else DATEPART(year, getdate()) end Yr) a
declare #today date = '2018-06-21'
select fin_year = dateadd(month, 3,
dateadd(year,
datepart(year,
dateadd(month, -3, #today)) - 1900, 0))
the expression datepart(year, dateadd(month, -3, #today)) is to get the current financial year. Since your financial year is Apr 1, for Jan 1 to Mar 31, subtracting 3 months from it, will give you the correct year (fiscal year = financial year).
After that it is just to form the date Apr 1 with that year
DECLARE #DateToUse DATETIME = GETDATE(),
#FinancialYearStart DATETIME
DECLARE #DayPart INT = DATEPART(DAY, #DateToUse),
#MonthPart INT = DATEPART(MONTH, #DateToUse),
#YearPart INT = DATEPART(YEAR, #DateToUse),
#StartMonth INT = 4, -- April
#StartDay INT = 1 -- 1st
SELECT DATETIMEFROMPARTS((
#YearPart - CASE
WHEN #MonthPart > #StartMonth
OR (
#MonthPart = #StartMonth
AND #DayPart >= #StartDay
)
THEN 0
ELSE 1
END
), #StartMonth, #StartDay, 0, 0, 0, 0)
I just knocked this up and it produces 2020-04-01 00:00:00.000 right now. I threw some other dates at it and it seemed to work nicely. Obviously the month/day can easily be changed by changing the variables at the top.
It's not the shortest block of SQL, but it's easy to use for different dates. A lot of other answers I've seen across different questions have returned different formats like a string or just the year part. Whereas this datetime will allow it to be used for datetime comparisons.
Need to check if today's date < 20 then set result var as 1st of next month.
If today's date > 20 then set result var as 1st of next month following the next month ?
Example:
for 24-09-2015 set result to 1st Nov 2015
for 19-09-2015 set result to 1st Oct 2015
This seems a bit tricky because of the date arithmetic:
set #var = (case when day(getdate()) < 20
then cast(dateadd(month, 1, dateadd(day, 1 - day(getdate()), getdate())) as date)
else cast(dateadd(month, 2, dateadd(day, 1 - day(getdate()), getdate())) as date)
end);
Here is a SQL Fiddle that shows the calculation.
This will give you the result:
DECLARE #d DATE = '20150924'
SELECT CASE WHEN DAY(#d) < 20
THEN DATEADD(mm, 1, DATEADD(dd, -DAY(#d) + 1, #d))
ELSE DATEADD(mm, 2, DATEADD(dd, -DAY(#d) + 1, #d)) END;
I am just finding a way to get a list of Start Week and End Week between two date range.
For e.g. if I call a function or a stored procedure say
GetWeekDates ('21 Mar 2014','21 Mar 2014')
Then I should get a table as:
Start Week | End Week
17 March 2014 | 23 Mar 2014
24 March 2014 | 30 Mar 2014
....
I don't want to use CURSOR or WHILE Loop.
Any direction where I should lead to?
I am just doing a re factor on existing code.
Kind regards,
Am
This will work as long as the intervals are 38 years or less. It will offer better performance and it does not rely on the local setting of the server.
This setting will cause your script to return wrong result:
set datefirst 1
select * from dbo.fnGetWeeksBetweenDates('2014-03-21','2014-03-21')
This means your local setting currently conflicts with your needs and your code is compensating.
Here is the script. The script is limited to 38 years for performance reasons (I find it unlikely that you need bigger intervals than that). It will be fairly easy to extend it to more years.
DECLARE #FromDate DATE = '2014-03-21'
DECLARE #ToDate DATE = '2014-03-24'
SELECT #fromdate = dateadd(day, datediff(day, 0, #FromDate)/7*7, 0),
#todate = dateadd(day, datediff(day, 0, #ToDate)/7*7, 6)
SELECT dateadd(d, number * 7, #fromdate) Start_Week,
dateadd(d, number * 7 + 6, #fromdate) End_Week
FROM
master..spt_values
WHERE type = 'P' and
#todate >= dateadd(d, number * 7, #fromdate)
Result:
Start_Week End_Week
2014-03-17 2014-03-23
2014-03-24 2014-03-30
I end up going through WITH statement and it is much faster than any other way; refactor mission accompliseded
CREATE FUNCTION fnGetWeeksBetweenDates
(
#FromDate DATETIME,
#ToDate DATETIME
) RETURNS #tbl TABLE (StartWeek date, EndWeek date)
AS BEGIN
DECLARE #TOTALWEEK INT
SET #FromDate = DATEADD(DAY,-1*DATEPART(dw,#FromDate)+2,#FromDate)
SET #TOTALWEEK = DATEDIFF(ww,#FromDate,#ToDate)+1;
WITH weekdays (StartWeek, EndWeek) as
(
select top (#TOTALWEEK) StartWeek = DateAdd(Week, ROW_NUMBER()
OVER (ORDER BY object_id)-1, #FromDate),
EndWeek = DateAdd(Week, ROW_NUMBER()
OVER (ORDER BY object_id)-1, #FromDate)
FROM SYS.all_objects
)
insert into #tbl
select StartWeek, DATEADD(day, 6, EndWeek) as EndWeek From weekdays;
RETURN
END;
Here is how you can call:
select * from dbo.fnGetWeeksBetweenDates('21 MAR 2014', '21 MAR 2015')
I'm trying to write a sql query to get last week's count in the format of mm/count/yyyy. In my situation, Wednesday starts a new week. So today March 8th, 2012 is the second week of March, and the last week count is 03/01/2012. Please note, the 01 means week count not date. If consider March 1st, 2012, the last week count should be the last week of Feburary which is 02/05/2012
Update: Thanks for Steve's comment, reminding me to clear my question here. Each month starts from it's first Wednesday. So the 03/01/2012 starts from March 7th, 2012 to March 13th, 2012
Any sql query solution?
I'm using sql-server
Here's some date logic to get you started. I can't comprehend your funky "last week count" definition by the two examples, so I can't code it.
DECLARE
#Now datetime,
#Today datetime,
#MonthStart datetime,
#WeekCount int,
#Result varchar(10)
SET #Now = GetDate()
SET #Today = DateAdd(dd, DateDiff(dd, 0, #Now), 0)
SET #MonthStart = DateAdd(mm, DateDiff(mm, 0, #Today), 0)
-- relative to the actual day the month started
SET #WeekCount = ((DatePart(dd, #Today)-1) / 7) + 1
-- relative to Sunday
--SET #WeekCount = (DatePart(week, #Today) - (DatePart(week, #MonthStart) + 1
SET #Result = convert(varchar(10), #Today, 101)
SET #Result =
LEFT(#Result, 3) -- month/
+ RIGHT('z00' + convert(varchar(2), #WeekCount), 2) -- week with zero pad
+ RIGHT(#Result, 5) -- /year
SELECT
#Now as TheNow,
#Today as Today,
#MonthStart as MonthStart,
#WeekCount as WeekCount,
#Result as Result
See also SET DATEFIRST
in oracle:
select to_char( sysdate, 'w' ) from dual
#Steven,
Sorry, this didn't fit as a comment.
Your description of "[nth] week in [month]" is not clear. Your week starts on Wednesday. February first was a Wednesday, so the weeks in February, 2012, if there are indeed 5 of them, are
February 1-7
February 8-14
February 15-21
February 22-28 and
February 29 - March 6
You describe March 8 as being in the "second week of March," so the first week of March must be the previous week, which is February 29 - March 6. Note that this is also what you call "the last (fifth) week in February."
By your description, then, the weeks you write as '02/05/2012' and '03/01/2012' are the same week with different names.
What is the rule that lets you know that
You want the same "last week" when you run the program March 1 as when you run it March 8
You want that week (which is the same) described differently in these two cases.
Or does your question have a mistake in it.
Once you can describe what you need, it will be easy to program. If you don't know what you want, it will be impossible to program.
In SQL Server these queries return 1,1,2,5
select ((DATEPART(dd, 'March 01, 2012')-1)/7) + 1
select ((DATEPART(dd, 'March 07, 2012')-1)/7) + 1
select ((DATEPART(dd, 'March 08, 2012')-1)/7) + 1
select ((DATEPART(dd, 'March 31, 2012')-1)/7) + 1
So this may be what you need
declare #dt datetime = 'March 31, 2012'
select
CONVERT(nvarchar(4), DATEPART(month,#dt)) + '/' +
CONVERT(nvarchar(4), ((DATEPART(dd, #dt)-1)/7) + 1) + '/' +
CONVERT(nvarchar(4), DATEPART(year,#dt))
which produces '3/5/2012'
SELECT
RIGHT(100 + MONTH(D) , 2) + '/' +
RIGHT(100 + (DAY(D) + 6) / 7, 2) + '/' +
DATENAME(YEAR, D)
FROM (
SELECT DATEADD(WEEK, -1, GETDATE()) AS D
) s
I think that should do it, I don't get the value for last week because it was confusing and the answer is cleaner that way, you can just add a DATEADD(day,-7,date) somewhere.
SET DATEFORMAT YDM
CREATE TABLE #Dates (Date DATETIME)
INSERT INTO #Dates VALUES ('2012-31-03');
INSERT INTO #Dates VALUES ('2012-15-02');
INSERT INTO #Dates VALUES ('2012-02-04');
INSERT INTO #Dates VALUES ('2012-02-05');
WITH Mondays as (
SELECT DATEADD(week, DATEDIFF(week,0, DATEADD(day,6-DATEPART(day,d.Date),d.Date) ), 0) FirstMonday,
DATEADD(week, DATEDIFF(week,0, DATEADD(day,6-DATEPART(day,DATEADD(month, -1, d.Date)),DATEADD(month, -1, d.Date)) ), 0) FirstMondayOfLastMonth,
d.Date
FROM #Dates d),
Wednesday as (
SELECT CASE WHEN DATEPART(day,m.FirstMonday) <= 5
THEN DATEADD(day,2,m.FirstMonday)
ELSE DATEADD(day,-5,m.FirstMonday) END FirstWednesday,
CASE WHEN DATEPART(day,m.FirstMondayOfLastMonth) <= 5
THEN DATEADD(day,2,m.FirstMondayOfLastMonth)
ELSE DATEADD(day,-5,m.FirstMondayOfLastMonth) END FirstWednesdayOfLastMonth,
m.Date
FROM Mondays m)
SELECT w.Date,
CASE WHEN w.Date >= w.FirstWednesday THEN
RIGHT('0' + CAST(DATEPART(month,w.Date) AS NVARCHAR(2)),2)
+ '/0' + CAST(DATEDIFF(week,w.FirstWednesday, w.Date) + 1 AS NVARCHAR(2))
+ '/' + CAST(DATEPART(year,w.Date) AS NVARCHAR(4))
ELSE
RIGHT('0' + CAST(DATEPART(month,w.FirstWednesdayOfLastMonth) AS NVARCHAR(2)),2)
+ '/0' + CAST(DATEDIFF(week,w.FirstWednesdayOfLastMonth, w.Date) + 1 AS NVARCHAR(2))
+ '/' + CAST(DATEPART(year,w.FirstWednesdayOfLastMonth) AS NVARCHAR(4))
END AS weekDate
FROM Wednesday w
DROP TABLE #Dates
The result is :
Date weekDate
2012-03-31 00:00:00.000 03/04/2012
2012-02-15 00:00:00.000 02/03/2012
2012-04-02 00:00:00.000 03/05/2012
2012-05-02 00:00:00.000 05/01/2012
I am building an SSRS report.
In the report, the week always runs from Monday - Sunday.
And I want to find out the START and END dates of prior two weeks.
For example,
If current date = Jan 1, 2011
-- current week = Dec 27, 2010 to Jan 2, 2011
-- previous week = Dec 20, 2010 to Dec 26, 2010
I have tried the following, but seems like it fails when when current day = Sunday
DECLARE #DT DATETIME
DECLARE #Offset INT
DECLARE #CM DATETIME
DECLARE #PM DATETIME
DECLARE #PS DATETIME
--SET #DT = GETDATE()
SET #DT = '11/14/2010' -- Monday
SET #Offset = (DATEPART(WEEKDAY, #DT) - 2) * -1
SET #CM = DATEADD(DAY, #Offset, #DT)
SET #PM = DATEADD(DAY, -7, #CM)
SET #PS = DATEADD(DAY, -1, #CM)
SELECT #Offset AS Offset, #DT AS Date, #CM AS Monday, #PM AS [Previous Monday], #PS AS [Previous Sunday], DATEPART(WK, #PM) AS Week
How can I fix it?
Add a [Calendar] table to your DB with all the dates you need precalculated. You can then include fields with the day name, number, holiday etc. and simply look up the values you need.
It's much simpler than playing with DATEADD
A useful article on calendar tables: Why should I consider using an auxiliary calendar table?
Not sure if this is the most elegant solution but you could do a case statement with your #offset like this:
SET #offset = CASE WHEN DATEPART(weekday, #today) >= 2
THEN -(DATEPART(weekday, #today) - 2)
ELSE -(DATEPART(weekday, #today) + 5)
END
I believe it works for all cases.