SQL Server : group by week off by 1 day - sql

Using the syntax
dateadd(week, datediff(week, 0, CURRENT_TIMESTAMP),0)
to group data by week it appears that the last day of the week gets put into the following week.
In a simple example
print dateadd(week, datediff(week, 0, '27 jan 2012 00:00'),0)
print dateadd(week, datediff(week, 0, '28 jan 2012 00:00'),0)
print dateadd(week, datediff(week, 0, '29 jan 2012 00:00'),0)
print dateadd(week, datediff(week, 0, '30 jan 2012 00:00'),0)
print dateadd(week, datediff(week, 0, '31 jan 2012 00:00'),0)
I would expect to return
Jan 23 2012 12:00AM
Jan 23 2012 12:00AM
Jan 23 2012 12:00AM
Jan 30 2012 12:00AM
Jan 30 2012 12:00AM
or
Jan 22 2012 12:00AM
Jan 22 2012 12:00AM
Jan 29 2012 12:00AM
Jan 29 2012 12:00AM
Jan 29 2012 12:00AM
depending on DATEFIRST settings I guess
however it returns
Jan 23 2012 12:00AM
Jan 23 2012 12:00AM
Jan 30 2012 12:00AM
Jan 30 2012 12:00AM
Jan 30 2012 12:00AM
i.e. the 29 January is in the week of 30th January not 23rd January or 30th January as expected.
I'm clearly missing something but can't think what it might be.

This is correct.
No matter what ##DATEFIRST is, there is always the same number of whole weeks between now and 01 Jan 1900. As ##DATEFIRST changes, it affects both "start" and "end" week.
DATEADD then just adds 7 day periods because it ignores ##DATEFIRST
You can force it by choosing the DATEADD base
Example: 01 Jan 1900 is a Monday.
You want Sunday? Then base to 31 Dec 1899
print dateadd(week, datediff(week, 0, '27 jan 2012 00:00'),-1)
print dateadd(week, datediff(week, 0, '28 jan 2012 00:00'),-1)
print dateadd(week, datediff(week, 0, '29 jan 2012 00:00'),-1)
print dateadd(week, datediff(week, 0, '30 jan 2012 00:00'),-1)
print dateadd(week, datediff(week, 0, '31 jan 2012 00:00'),-1)
You want Tuesday? Then base to 02 Jan 1900
print dateadd(week, datediff(week, 0, '27 jan 2012 00:00'),1)
print dateadd(week, datediff(week, 0, '28 jan 2012 00:00'),1)
print dateadd(week, datediff(week, 0, '29 jan 2012 00:00'),1)
print dateadd(week, datediff(week, 0, '30 jan 2012 00:00'),1)
print dateadd(week, datediff(week, 0, '31 jan 2012 00:00'),1)

This should convert the date to the first day of the week for the purposes of grouping
set datefirst 1
select dateadd(day, -1 * (datepart(weekday, getdate()) - 1), getdate())
Note that the set datefirst 1 sets the first day of the week as Monday. You can alter this statement to change the first day of the week to fit to your expectations (see http://msdn.microsoft.com/en-us/library/ms181598.aspx)

DATEDIFF doesn't respect the DATEFIRST setting.
Here's a similar question, with a potential workaround:
Is it possible to set start of week for T-SQL DATEDIFF function?

Related

How to get data from Jan to last month in current month

I have a requirement where I need the data from Jan to last month, so for Dec 2017 I want the data from Jan 2017 - Nov 2017 , and in Jan 2018 I want the data from jan 2017 - Dec 2017, in feb 2018 I want the data from 1st Jan 2018- 31st Jan 2018, in March I want Jan 2018 - Feb 2018 and so on.
Below is my code:
(case when (DateFilled) between cast (DATEADD(YEAR, DATEDIFF(YEAR, '19000101', '2018-01-05'), '19000101') as datetime)
and cast (DATEADD(D, -1, DATEADD(MONTH, DATEDIFF(MONTH, '19000101', '2018-01-05'), '19000101')) as datetime)
THEN 1 else 0 end) as numeric(10,2) [TillLastMonth]
(Datefilled is the column with datatime datatype)
Any help is appreciated!!
Thanks

SQL date convert from 20 Dec 2016 to 20 December 2016

current SQL to get 20 Dec 2016 is:
Convert(char(11), getdate(), 13) DATE,
SELECT FORMAT(cast('20 DEC 2016' as date),'dd MMMM yyyy')

SQL - pick current date from machine and compare the year

Scenario 1: Current Year
Always code needs to pick
The last Sunday of January for the current year. For ex(31-01-2016)
Current code - picks 1st of Jan 2016
convert(date,DATEADD(yy, DATEDIFF(yy, 0, getdate()), 0))
Scenario 2: Last Year
Always code needs to pick
The last Sunday of January for the Previous year. For ex(01-02-2015)
Current code - picks 1st of Jan 2015
convert(date,DATEADD(yy, DATEDIFF(yy, 0, dateadd(YEAR, - 1, getdate())), 0))
Instead of hard coding the date. I would like to pick date from machine and compare.
Week start from Sunday and ends Saturday. Any help please?
-- Sample Demonstrative Data/Test Results
Declare #YourTable table (SomeDate date)
Insert Into #YourTable values ('2000-06-15'),('2001-06-15'),('2002-06-15'),('2003-06-15'),('2004-06-15'),('2005-06-15'),('2006-06-15')
,('2007-06-15'),('2008-06-15'),('2009-06-15'),('2011-06-15'),('2012-06-15'),('2013-06-15'),('2014-06-15'),('2015-06-15'),('2016-06-15')
,('2017-06-15'),('2018-06-15'),('2019-06-15'),('2020-06-15')
-- To Confirm Results
Select Year = year(SomeDate)
,LastSundayDate = DateAdd(DD,-DatePart(DW,DateFromParts(Year(SomeDate),12,31))+1,DateFromParts(Year(SomeDate),12,31))
,LastSundayName = DateName(DW,DateAdd(DD,-DatePart(DW,DateFromParts(Year(SomeDate),12,31))+1,DateFromParts(Year(SomeDate),12,31)))
From #YourTable
Returns
Year LastSundayDate LastSundayName
2000 2000-12-31 Sunday
2001 2001-12-30 Sunday
2002 2002-12-29 Sunday
2003 2003-12-28 Sunday
2004 2004-12-26 Sunday
2005 2005-12-25 Sunday
2006 2006-12-31 Sunday
2007 2007-12-30 Sunday
2008 2008-12-28 Sunday
2009 2009-12-27 Sunday
2011 2011-12-25 Sunday
2012 2012-12-30 Sunday
2013 2013-12-29 Sunday
2014 2014-12-28 Sunday
2015 2015-12-27 Sunday
2016 2016-12-25 Sunday
2017 2017-12-31 Sunday
2018 2018-12-30 Sunday
2019 2019-12-29 Sunday
2020 2020-12-27 Sunday

How to subtract 30 days from the current date using SQL Server

I am unable subtract 30 days from the current date and I am a newbie to SQL Server.
This is the data in my column
date
------------------------------
Fri, 14 Nov 2014 23:03:35 GMT
Mon, 03 Nov 2014 15:18:00 GMT
Tue, 11 Nov 2014 01:24:47 GMT
Thu, 06 Nov 2014 19:13:47 GMT
Tue, 04 Nov 2014 12:37:06 GMT
Fri, 1 Nov 2014 00:33:00 GMT
Sat, 5 Nov 2014 01:06:00 GMT
Sun, 16 Nov 2014 06:37:12 GMT
For creating the above column I used varchar(50) and now my problem is I want to display the dates for past 15-20 days from the date column can any one help with this issue ?
update [ how can i display last 7 days dates in order
You can convert it to datetime, and then use DATEADD(DAY, -30, date).
See here.
edit
I suspect many people are finding this question because they want to substract from current date (as is the title of the question, but not what OP intended). The comment of munyul below answers that question more specifically. Since comments are considered ethereal (may be deleted at any given point), I'll repeat it here:
DATEADD(DAY, -30, GETDATE())
Try this:
SELECT GETDATE(), 'Today'
UNION ALL
SELECT DATEADD(DAY, 10, GETDATE()), '10 Days Later'
UNION ALL
SELECT DATEADD(DAY, –10, GETDATE()), '10 Days Earlier'
UNION ALL
SELECT DATEADD(MONTH, 1, GETDATE()), 'Next Month'
UNION ALL
SELECT DATEADD(MONTH, –1, GETDATE()), 'Previous Month'
UNION ALL
SELECT DATEADD(YEAR, 1, GETDATE()), 'Next Year'
UNION ALL
SELECT DATEADD(YEAR, –1, GETDATE()), 'Previous Year'
Result Set:
———————– —————
2011-05-20 21:11:42.390 Today
2011-05-30 21:11:42.390 10 Days Later
2011-05-10 21:11:42.390 10 Days Earlier
2011-06-20 21:11:42.390 Next Month
2011-04-20 21:11:42.390 Previous Month
2012-05-20 21:11:42.390 Next Year
2010-05-20 21:11:42.390 Previous Year
TRY THIS:
Cast your VARCHAR value to DATETIME and add -30 for subtraction. Also, In sql-server the format Fri, 14 Nov 2014 23:03:35 GMT was not converted to DATETIME. Try substring for it:
SELECT DATEADD(dd, -30,
CAST(SUBSTRING ('Fri, 14 Nov 2014 23:03:35 GMT', 6, 21)
AS DATETIME))
SELECT DATEADD(day,-30,date) AS before30d
FROM...
But it is strongly recommended to keep date in datetime column, not varchar.

Changing date format for PostgreSQL query result

I have following query
select substring(listDate from '............$') as v_end_date,
substring(listDate from '^...............') as v_start_date
Now listDate value can be like
select substring('06 Jan 2014 to 12 Jan 2014,
13 Jan 2014 to 19 Jan 2014,
20 Jan 2014 to 26 Jan 2014
' from '............$') as v_end_date,
substring('06 Jan 2014 to 12 Jan 2014,
13 Jan 2014 to 19 Jan 2014,
20 Jan 2014 to 26 Jan 2014
' from '^............') as v_start_date
Above query results in
V_END_DATE V_START_DATE
26 Jan 2014 06 Jan 2014
Now I need to have v_end_date and v_start_date format like yyyy-mm-dd and like
Mon 06 Jan 2014.
Convert your string to an actual date with to_date() and use to_char() to get pretty much any format you like.
Demo:
SELECT to_char(day, 'YYYY-MM-DD') AS format1
, to_char(day, 'Dy DD Mon YYYY') AS format2
FROM (SELECT to_date('26 Jan 2014', 'DD Mon YYYY') AS day) sub