I have two dates say '2011-01-23' and '2015-11-29',
'2011-01-23' falls in first quarter of 2011 so 'Jan 2011'
'2015-11-29' falls in fourth quarter of 2015 so 'Oct 2015'
In SQL Server I want get all quarters in a select list.
e.g.
Input: #StartDate='2011-01-23' , #EndDate='2015-11-29'
Output:
Jan 2011
Apr 2011
Jul 2011
Oct 2011
Jan 2012
Apr 2012
Jul 2013
Oct 2013
Jan 2014
......
......
......
Jul 2015
Oct 2015
You can use a recursive CTE to generate the dates as follows:
declare #StartDate datetime
declare #EndDate datetime
select #StartDate='2011-01-23' , #EndDate='2015-11-29'
;With Quarters as (
select DATEADD(quarter,DATEDIFF(quarter,0,#StartDate),0) as dt
union all
select DATEADD(quarter,1,dt)
from Quarters
where dt < DATEADD(quarter,DATEDIFF(quarter,0,#EndDate),0)
)
select
--I'd usually keep them as dates at this point, but to match your requirement
CONVERT(varchar(3),dt,109) + ' ' + CONVERT(varchar(4),dt,120)
from Quarters order by dt
This also uses a couple of other tricks - it uses CONVERT with far too short target datatypes to quickly truncate the strings to just the parts that we want to keep - and it uses a DATEADD/DATEDIFF pair to quickly round a datetime value down to it's nearest interval boundary.
For SQL Server 2012, you could instead use FORMAT to produce the output string, but I've not experimented with that much so I'll leave that as an exercise...
Finally, I found the solution of my question..
WITH mycte AS
(
SELECT CAST('2011-01-01' AS DATE) DateValue
UNION ALL
SELECT DATEADD(Q,1,DateValue) FROM mycte WHERE DATEADD(Q,1,DateValue) < '2012-12-31'
)
SELECT CONVERT(varchar(3), DATENAME(MONTH,DateValue))+ ' ' +Convert(varchar(4),DATEPART(YYYY,DateValue)) FROM mycte OPTION (MAXRECURSION 0)
Related
I have a table containing two columns like this:
Month_Date Year
Dec 31 2018
May 01 2020
Jun 05 2021
Jan 18 2022
Jul 19 2019
I hope to combine the Month_date and year in the same row and put it in a new column as a datetime format column. Could anyone help, please? I tried to convert the first column to a valid date, but failed because it doesn't show a complete month name.
You can try below approach.
Approach1:
select convert(datetime, [Month_Date] + ', ' + cast([Year] as varchar(4)), 107) from <TableName>
Approach2:
select cast(right(month_date,2)+'-'+left(month_date,3)+'-'+cast([Year] as varchar(4)) as date) from <TableName>
I have a table which includes the columns Season and Academic_Year. Academic_Year is type int. Season can be Spring, Summer or Fall.
Fall 2016 is from 1 Sep 2016 to 31 Dec 2016.
Spring 2016 is from 1 Jan 2017 to 31 Mar 2017 (not a typo - the Academic Year 2016 is from Sep 2016 to Aug 2017)
Summer 2016 is from 1 Apr 2017 to 31 Aug 2017
I need to select rows when getdate() is between a number of days before and after the start of the Season, in pseudo code
WHERE
( getdate() > 31/3/16 AND getdate() < 31/9/16 AND Season = 'Autumn' AND Academic_Year = 2016 )
OR ( getdate() > 31/9/16 AND getdate() < 31/1/17 AND Season = 'Spring' AND Academic_Year = 2016 )
OR ( getdate() > 31/12/16 AND getdate() < 31/4/17 AND Season = 'Summer' AND Academic_Year = 2016 )
My problem is creating the date for comparison with getdate(). I need to combine a string - '31/3/' - with an int - Academic_Year, and create a date.
The solution does not need to be efficient but it does need to work on 2008 and later sql server versions.
SQL will allow this conversion if you just concatenate the varchars and tell it to convert to date. For example:
declare #year int = 2016
declare #date varchar(10) = '3/31'
select cast(#date + '/' + cast(#year as varchar(4)) as date)
You have to cast the integer year to varchar to combine it with the other varchar, but you can then cast the entire thing to a date (or datetime) once you have a recognized date format.
You can form your date by doing by using concatenation of the string and year.
CONVERT(VARCHAR(4), Academic_Year) + '-03-31'
Once you have the date string you could use the date functions to manipulate it further if necessary.
WHERE (GETDATE() > CONVERT(VARCHAR(4),Academic_Year) + '-03-31'
AND GETDATE() < CONVERT(VARCHAR(4),Academic_Year) + '-09-30'
AND Season = 'Autumn') etc
worked for me. The trick was adding '-03-31' rather than preceeding with '31-03-'. Thanks #kicken
I imported a table into SQL Server 2014 and I found that the date format is in BST and GST format. I want to create a view and change the whole column to SQL Server date type to perform operations. I don't mind truncating the time section.
Wed Apr 07 00:00:00 BST 1943
Tue Jan 08 00:00:00 GMT 1985
I was able to do it in Excel with the following formula but want to do it in SQL Server:
=IFERROR(DATEVALUE(MID(E2,9,2)&"-"&MID(E2,5,3)&"-"&RIGHT(E2,4)), "")
All I am looking for is
1943-04-07
1985-01-08
This solution assumes that every row in the source data follows the same format. If there are any fringe cases these will fail.
With SQL Server 2012, and higher, you have the handy DATEFROMPARTS function. This function returns a date when passed a year, month and day. These can be extracted with SUBSTRING and RIGHT from the source string.
Extracting the month number (1~12) is achieved by building an arbitrary date string (01-mmm-2000). This is cast into a date, from which the month number is extracted. Generally speaking I would't recommend using date strings in any format other than YYYY-MM-DD. However this avoids the use of a CTE, which OP was keen to do.
Example
/* Let's create some sample values to
* experiment with.
*/
DECLARE #Sample TABLE
(
DateVal VARCHAR(50)
)
;
INSERT INTO #Sample
(
DateVal
)
VALUES
('Wed Apr 07 00:00:00 BST 1943'),
('Tue Jan 08 00:00:00 GMT 1985')
;
/* Extracting the month number is achieved by first casting the 3 character month
* name as a full date, by appended a day and year. Then the month number is
* extracted from this.
*/
SELECT
s.DateVal,
SUBSTRING(s.DateVal, 9, 2) AS [Day],
MONTH(CAST('01-' + SUBSTRING(s.DateVal, 5, 3) + '-2000' AS DATE)) AS [Month],
RIGHT(s.DateVal, 4) AS [Year],
-- Reuse the values shown above.
DATEFROMPARTS(
RIGHT(s.DateVal, 4),
MONTH(CAST('01-' + SUBSTRING(s.DateVal, 5, 3) + '-2000' AS DATE)),
SUBSTRING(s.DateVal, 9, 2)
) AS [Date]
FROM
#Sample AS s
;
EDIT: The original solution contained a CTE, used to look up the month number from a 3 character month name. This has been replaced.
SELECT CONVERT(date, RIGHT(DateColumn, 4)+ '-' + RIGHT('0' + Convert(nvarchar, (Month(SUBSTRING(DateColumn, 5, 3) + '2016'))), 2) + '-' + SUBSTRING(DateColumn, 9, 2)) as dob
FROM MyTable
Your sample output doesn't match your input data. I think you meant 1985-01-08.
For a shorter solution, you can use CAST or CONVERT with style 107. It expects the string to be in the Mon dd, yyyy format:
SELECT CONVERT(datetime, SUBSTRING(DateColumn, 5, 6) + ', ' + RIGHT(DateColumn, 4), 107)
FROM MyTable
How can I extract the year and week combination from a date in SQL Server using T-SQL and have it match the MySQL yearweek result?
For example these MySQL queries (Click here for MySQL SQL Fiddle):
SELECT yearweek('2013-12-31');
SELECT yearweek('2014-01-01');
This returns 201352 for both dates. That is the expected result.
But in SQL Server...
datepart works as expected for the year extract
sometimes datepart does not return the expected value for iso_week
The MySQL result cannot be achieved with this T-SQL query...
SELECT datepart(year, #dt) * 100 + datepart (iso_week, #dt);
T-SQL versions of the MySQL queries above (Click here for T-SQL SQL Fiddle):
SELECT datepart(year, '2013-12-31') * 100 + datepart (iso_week, '2013-12-31');
SELECT datepart(year, '2014-01-01') * 100 + datepart (iso_week, '2014-01-01');
The result is 201352 for the first date and 201401 for the second date.
However, this is not the expected result because...
2014-01-01 belongs to the last week of 2013
So the expected result is 201352
Do any of you more experienced T-SQL developers know how to extract the year/week of a given date and have this match what I see in MySQL?
I need to have the week start on Monday. This is why I am using iso_week. I have tested the results with week anyway and found the same issue. This query also produces 201401 when 201352 is expected.
SELECT datepart(year, '2014-01-01') * 100 + datepart (week, '2014-01-01');
If you look at the ISO_Week datepart definition at http://msdn.microsoft.com/en-us/library/ms174420.aspx, you'll see the following:
ISO 8601 includes the ISO week-date system, a numbering system for
weeks. Each week is associated with the year in which Thursday
occurs...
The numbering system in different countries/regions might not comply
with the ISO standard.
Since January 1, 2014 was a Wednesday; January 2, 2014 was the first Thursday of the year and thus week 1 of 2014 (according to ISO 8601).
Furthermore, looking at the MySQL definitions for yearweek and week, there are several mode options (http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_week)
So, I think you're going to have to write your own yearweek function for the week counting rule you want:
CREATE FUNCTION dbo.yearweek(#date date)
RETURNS INT
as
begin
set #date = dateadd(dd,-datepart(dw,#date)+1, #date)
return datepart(year,#date)*100 + datepart(week,#date)
end
go
select dbo.yearweek('2013-12-31'), dbo.yearweek('2014-01-01')
NOTE: I haven't fully tested this code, and I'm not sure exactly what your requirements are. This is just meant as an example of the type of process you need to follow.
I think it's because you're using "ISO_WEEK" as the datepart
Look at the description under the "ISO_WEEK datepart" here: http://msdn.microsoft.com/en-us/library/ms174420.aspx
using "WEEK" instead might get the desired result
TO extract YEAR, MONTH or DAY you can simply use the YEAR, MONTH and DAY function as shown in the followinf example. for any other part you have to use the DATEPART function , read here for a detailed list of arguements you can pass to DATEPART function.
SELECT YEAR(GETDATE()) AS [YEAR]
, DATEPART(WEEK, GETDATE()) [Week]
UPDATE
SELECT CAST(YEAR(GETDATE()) AS VARCHAR(4)) +'-'
+ CAST(DATEPART(WEEK, GETDATE()) AS VARCHAR(2))
It seems to me that what you want is a week number based on the previous Monday. Is this correct? If so, iso_week is no use to you as it is based on this week's Thursday.
To get the year and week based on the previous Monday, I think you need something like the following.
set datefirst 1 ;
select
SomeDate ,
datename( weekday, SomeDate ) as [WeekdayName] ,
datepart( weekday, SomeDate ) as [Weekday] ,
datepart( week, SomeDate ) as [Week] ,
datepart( iso_week, SomeDate ) as [ISO_week] ,
dateadd( day, -( datepart( weekday, SomeDate ) - 1 ), SomeDate ) as [PreviousMonday] ,
datepart( year, dateadd( day, -( datepart( weekday, SomeDate ) - 1 ), SomeDate ) ) as [MondayYear] ,
datepart( week, dateadd( day, -( datepart( weekday, SomeDate ) - 1 ), SomeDate ) ) as [MondayWeek]
from
dbo.DateDemo
order by
SomeDate ;
Abbreviated sample output is as follows.
SomeDate PreviousMonday MondayYear MondayWeek
2013-12-25 2013-12-23 2013 52
2013-12-26 2013-12-23 2013 52
2013-12-27 2013-12-23 2013 52
2013-12-28 2013-12-23 2013 52
2013-12-29 2013-12-23 2013 52
2013-12-30 2013-12-30 2013 53
2013-12-31 2013-12-30 2013 53
2014-01-01 2013-12-30 2013 53
2014-01-02 2013-12-30 2013 53
2014-01-03 2013-12-30 2013 53
2014-01-04 2013-12-30 2013 53
2014-01-05 2013-12-30 2013 53
2014-01-06 2014-01-06 2014 2
I am building a report which has the header field as PropertyStatementForHalfyear Ending :<Date>
So in the DATE field I need to put either May 28 or Nov 28 depending on the date the report Runs
Whats The logic I need to write ??
For example if I run the report today i.e. June 22, I need to display PropertyStatementForHalfyear Ending : 28 Nov 2013
if I run it in December 2013, I need to display PropertyStatementForHalfyear Ending : 28 May 2014
You could use something like this:
DECLARE #DateThreshold1 DATE = '20130528'
DECLARE #DateThreshold2 DATE = '20131128'
DECLARE #CurrentDate DATE = '20131201'
IF #CurrentDate > #DateThreshold2
SELECT CONVERT(VARCHAR(50), DATEADD(YEAR, 1, #DateThreshold1), 106)
ELSE IF #CurrentDate > #DateThreshold1
SELECT CONVERT(VARCHAR(50), #DateThreshold2, 106)
ELSE
SELECT CONVERT(VARCHAR(50), #DateThreshold1, 106)
For dates from 20130101 through 20130528, this will return 28 May 2013
For dates from 20130529 through 20131128, this will return 28 Nov 2013
For dates past 20131128, this will return 28 May 2014
You can easily package this up into a function or a SSRS code snippet
If you're not into IF/CASE statements, like me:
with dt as
(select CAST('2013-11-28' as datetime) dt) --dt becomes your datetime column.
, ymdt as (select
DATEPART(year, dt) y,
DATEPART(month, dt) m,
DATEPART(day, dt) d,
dt
from dt) --split into year, month and date for readability
select y, m, d, dt,
DATEADD(month, 5 + d/28 - (m + d/28) % 6, --add months depending on month and day
DATEADD(day, 28 - d --go to the correct day
, dt) --start calculation from dt (the sql date functions' parameter order has always baffled me)
) HalfYearEndDate
from ymdt
The SQL engine merges all of this into one big fat constant scan or scalar expression on your datetime column.
You should create a SQL or VB function for this if you need this in other reports and also so it doesn't clutter up your queries.
Also: Don't do text formatting in T-SQL unless absolutely necessary! Return a datetime column and do it in the report itself. The format you need to set on the textbox is "dd MMM yyyy" (without the quotes when using the designer).