Remove the time part in Datediff - sql-server

This is my query:
SELECT DISTINCT
'wk ' + TRIM(CONVERT(varchar(max), DATEADD(Week, DATEDIFF(week, 0, CONVERT(VARCHAR(max), period)), -1))) [week]
FROM
ABC
GROUP BY
TRIM(CONVERT(varchar(max), DATEADD(Week, DATEDIFF(week, 0, CONVERT(VARCHAR(max), period)), -1)))
I get a result like this: wk Aug 7 2022 12:00AM
But I want this format wk Aug 7, 2022

There was an error in the answer, it always returned january, the error is fixed now
You could build your string using the datepart function
declare #period datetime = '20220807' -- getdate()
SELECT 'wk ' +
left(datename(month, #period), 3) +
' ' + convert(varchar(2), datepart(day, #period)) +
' ,' + convert(varchar(4), datepart(year, #period))
looks like this wk Aug 7 ,2022
To convert your select clause to use this,
declare #table1 table (id int, period date)
insert into #table1 (id, period) values (1, '20220807'), (2, '20211130')
SELECT 'wk ' +
left(datename(month, dateadd( week, DATEDIFF( week, 0, CONVERT(VARCHAR(12), convert(date, period))), -1)), 3) +
' ' + convert(varchar(2), datepart(day, dateadd( week, DATEDIFF( week, 0, CONVERT(VARCHAR(12), convert(date, period))), -1))) +
' ,' + convert(varchar(4), datepart(year, dateadd( week, DATEDIFF( week, 0, CONVERT(VARCHAR(12), convert(date, period))), -1)))
from #table1
it looks like this
COLUMN1
wk Aug 7 ,2022
wk Nov 28 ,2021

Related

Use MAX(Date) value inside a SQL recursion

I have SQL query with performs recursion based on selected Min(Date) and Max(Date) from more than 1 table. But when i try to run the query it throws GROUP BY, HAVING, or aggregate functions are not allowed in the recursive part of a recursive common table expression 'ctedaterange'. exception. I also tried using Top 1 Date but still no hope.
SQL Query
ALTER VIEW [dbo].[CYExtraction]
AS
WITH ctedaterange
AS (SELECT
[Dates] = (SELECT
MIN(CreatedOn) AS CreatedOn
FROM (SELECT
MIN(CreatedOn) AS CreatedOn
FROM (SELECT
MIN(CreatedOn) AS CreatedOn
FROM Items) AS it
UNION ALL
SELECT
*
FROM (SELECT
MIN(CreatedOn) AS CreatedOn
FROM Bibs) AS bib
UNION ALL
SELECT
*
FROM (SELECT
MIN(CreatedOn) AS CreatedOn
FROM Porders) AS po) AS AllItems)
UNION ALL
SELECT
[dates] + 1
FROM ctedaterange
WHERE [dates] + 1 <= (SELECT
MAX(CreatedOn) AS CreatedOn
FROM (SELECT
MAX(CreatedOn) AS CreatedOn
FROM (SELECT
MAX(CreatedOn) AS CreatedOn
FROM Items) AS it
UNION ALL
SELECT
*
FROM (SELECT
MAX(CreatedOn) AS CreatedOn
FROM Bibs) AS bib
UNION ALL
SELECT
*
FROM (SELECT
MAX(CreatedOn) AS CreatedOn
FROM Porders) AS po) AS AllItems))
SELECT
[Dates] AS PK_Date,
DATENAME(MONTH, [Dates]) + ' ' + CAST(YEAR([Dates]) AS varchar(4)) AS
Month,
CASE
WHEN DATEPART(m, [Dates]) <= 3 THEN 'Q1 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE CASE
WHEN DATEPART(m, [Dates]) <= 6 THEN 'Q2 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE CASE
WHEN DATEPART(m, [Dates]) <= 9 THEN 'Q3 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE CASE
WHEN DATEPART(m, [Dates]) <= 12 THEN 'Q4 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE ''
END
END
END
END AS 'Quarter',
CASE
WHEN DATEPART(m, [Dates]) <= 6 THEN 'HY1 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE CASE
WHEN DATEPART(m, [Dates]) <= 12 THEN 'HY2 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE ''
END
END AS 'HalfYear',
YEAR([Dates]) AS 'Year',
CAST('1-' AS varchar(5)) + CAST(DATEPART(M, [Dates]) AS varchar(10)) + '-' + CAST(YEAR([Dates]) AS varchar(4)) AS DateName
FROM ctedaterange
GO
The main thing is that I need to wrap it inside my SQL Views. Any help to my problem will be appreciated.
Thanks,
You can move the aggregations to an extra cte, so this might be what you want:
ALTER VIEW [dbo].[CYExtraction]
(PK_Date, [Month], [Quarter], [HalfYear], [Year], [DateName])
AS
WITH cteAllItems (mindates, maxdates) AS (
SELECT MIN(CreatedOn), MAX(CreatedOn) FROM Items
UNION ALL
SELECT MIN(CreatedOn), MAX(CreatedOn) FROM Bibs
UNION ALL
SELECT MIN(CreatedOn), MAX(CreatedOn) FROM Porders
),
ctedaterange (Dates, MaxDate) AS (
SELECT MIN(mindates), MAX(maxdates)
FROM cteAllItems
UNION ALL
SELECT DATEADD(day, 1, Dates), MaxDate
FROM ctedaterange
WHERE DATEADD(day, 1, Dates) <= MaxDate
)
SELECT
Dates AS PK_Date,
DATENAME(MONTH, Dates) + N' ' + DATENAME(YEAR, Dates),
N'Q' + DATENAME(QUARTER, Dates) + N' ' + DATENAME(YEAR, Dates),
N'HY' + CAST((MONTH(Dates)-1)/6+1 AS nvarchar(1)) + N' ' + DATENAME(YEAR, Dates),
YEAR(Dates),
CONVERT(nvarchar(10), DATEADD(MONTH, DATEDIFF(MONTH, 0, Dates), 0), 105)
FROM ctedaterange
GO

SQL server date time

I am trying to get object which its start date + start time have passed or equal to current datetime and its end date + end time hasn't pass the current datetime. I tried convert current datetime to nvarchar as all my columns are nvarchar. I also tried converting my columns to datetime type but it doesn't work too. Please help
Column:
startDate - nvarchar (dd/mm/yyyy)
startTime - nvarchar (hh:mm) 24 hr
endDate - nvarchar(dd/mm/yyyy)
endTime - nvarchar(hh:mm) 24hr
i did try to but datetime betwween startDate + startTime AND endDate +startTime,
but it doesn't seems to work :
SELECT * FROM Promo
WHERE membership = '1'
AND promoStatus = '1'
AND CONVERT(NVARCHAR, GetDate(), 101) + ' ' +
CONVERT(NVARCHAR, DATEPART(hh, GetDate())) + ':' +
RIGHT('0' + CONVERT(NVARCHAR, DATEPART(mi, GetDate())), 2) BETWEEN
startDate + ' ' + startTime
AND endDate + ' ' + endTime
i did try other method too :
SELECT * FROM Promo
WHERE membership = '1'
AND promoStatus = '1'
AND startDate + ' ' + startTime <= CONVERT(NVARCHAR, GetDate(), 101) + ' ' +
CONVERT(NVARCHAR, DATEPART(hh, GetDate())) + ':' +
RIGHT('0' + CONVERT(NVARCHAR, DATEPART(mi, GetDate())), 2)
AND endDate + ' ' + endTime >= CONVERT(NVARCHAR, GetDate(), 101) + ' ' +
CONVERT(NVARCHAR, DATEPART(hh, GetDate())) + ':' +
RIGHT('0' + CONVERT(NVARCHAR, DATEPART(mi, GetDate())), 2)
You could do it like this:
SELECT *
FROM Promo
WHERE
membership = '1'
AND promoStatus = '1'
AND CAST(CONVERT(VARCHAR(16), GETDATE(), 120) AS DATETIME) BETWEEN
CONVERT(DATETIME, #startDate, 103) + CONVERT(DATETIME, #startTime)
AND CONVERT(DATETIME, #endDate, 103) + CONVERT(DATETIME, #endTime)
This line:
CAST(CONVERT(VARCHAR(16), GETDATE(), 120) AS DATETIME)
gets the current date time up to its minutes, meaning this will strip off the seconds and milliseconds part of the GETDATE().
And this line:
CONVERT(DATETIME, #startDate, 103) + CONVERT(DATETIME, #startTime)
will combine your date and time variables to form a new DATETIME value.
Note that you could have done away with with this if you design the tables using the proper data types.
Try this
SELECT * FROM Promo
WHERE membership = '1'
AND promoStatus = '1'
AND CAST(CONVERT(VARCHAR(16), GetDate(), 120) AS DATETIME)
BETWEEN CONVERT(DATETIME, startDate + ' ' + startTime, 120)
AND CONVERT(DATETIME, endDate + ' ' + endTime, 120)

PL/SQL to TSQL conversion

I have used a tool to convert PL/SQL to TSQL but I am getting weird errors for some cases.
CREATE PROC Dates
(
#PeriodType varchar(15),
#ReportStart varchar(15),
#ReportEnd varchar(15)
)
AS
BEGIN
SELECT CASE
WHEN #PeriodType = 'CUR_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 1 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112))
WHEN #PeriodType = 'NEXT_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 8 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112))
WHEN #PeriodType = 'PREV_DAY' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - 1, 112))
WHEN #PeriodType = 'PREV_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - 6 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112))
WHEN #PeriodType = 'PREV_2WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - 13, 112))
WHEN #PeriodType = 'CUR_MONTH' THEN CONVERT(DATETIME, CAST(CONVERT(VARCHAR(23), GETDATE()) AS VARCHAR) + '01', 112)
WHEN #PeriodType = 'DATE_RANGE' THEN CONVERT(DATETIME, #ReportStart)
END AS "StartDate",
CASE
WHEN #PeriodType = 'CUR_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 8 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112)) - (1 / CONVERT(FLOAT, 86400))
WHEN #PeriodType = 'NEXT_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 15 - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112)) - (1 / CONVERT(FLOAT, 86400))
WHEN #PeriodType = 'PREV_DAY' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE(), 112)) - (1 / CONVERT(FLOAT, 86400))
WHEN #PeriodType = 'PREV_WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() - CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE())), 112)) + 1 - (1 / CONVERT(FLOAT, 86400))
WHEN #PeriodType = 'PREV_2WEEK' THEN CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE() + 1, 112)) - (1 / CONVERT(FLOAT, 86400))
WHEN #PeriodType = 'CUR_MONTH' THEN DATEADD(M, 1, CONVERT(DATETIME, CONVERT(VARCHAR, GETDATE(), 112)) - (CONVERT(NUMERIC(8, 2), DATEPART(DD, GETDATE())) - 1)) - 1
WHEN #PeriodType = 'DATE_RANGE' THEN CONVERT(DATETIME, #ReportEnd) + 1
END AS "EndDate"
END
My stored proc is executing for PREV_DAY and PREV_2WEEK for the remaining period type I am getting conversions errors.
exec proc Dates 'PREV_DAY','',''
exec proc Dates 'PREV_2WEEK','',''
My PL\SQL code is
SELECT CASE
WHEN :PeriodType = 'CUR_WEEK'
THEN TRUNC(SYSDATE + 1 - TO_NUMBER(TO_CHAR(SYSDATE, 'D')))
WHEN :PeriodType = 'NEXT_WEEK'
THEN TRUNC(SYSDATE + 8 - TO_NUMBER(TO_CHAR(SYSDATE, 'D')))
WHEN :PeriodType = 'PREV_DAY'
THEN TRUNC(SYSDATE - 1)
WHEN :PeriodType = 'PREV_WEEK'
THEN TRUNC(SYSDATE - 6 - TO_NUMBER(TO_CHAR(SYSDATE, 'D')))
WHEN :PeriodType = 'PREV_2WEEK'
THEN TRUNC(SYSDATE - 13)
WHEN :PeriodType = 'CUR_MONTH'
THEN to_date(to_char(sysdate,'YYYYMM') || '01','YYYYMMDD')
WHEN :PeriodType = 'DATE_RANGE'
THEN TO_DATE(:ReportStart)
END AS "StartDate",
CASE
WHEN :PeriodType = 'CUR_WEEK'
THEN TRUNC(SYSDATE + 8 - TO_NUMBER(TO_CHAR(SYSDATE, 'D'))) - (1/86400)
WHEN :PeriodType = 'NEXT_WEEK'
THEN TRUNC(SYSDATE + 15 - TO_NUMBER(TO_CHAR(SYSDATE, 'D'))) - (1/86400)
WHEN :PeriodType = 'PREV_DAY'
THEN TRUNC(SYSDATE)-(1/86400)
WHEN :PeriodType = 'PREV_WEEK'
THEN TRUNC(SYSDATE - TO_NUMBER(TO_CHAR(SYSDATE, 'D'))) + 1 - (1/86400)
WHEN :PeriodType = 'PREV_2WEEK'
THEN TRUNC ( SYSDATE+1) - (1/86400)
WHEN :PeriodType = 'CUR_MONTH'
THEN ADD_MONTHS(TRUNC(SYSDATE) - (TO_NUMBER(TO_CHAR(SYSDATE,'DD')) - 1), 1) -1
WHEN :PeriodType = 'DATE_RANGE'
THEN TO_DATE(:ReportEnd)+1
END AS "EndDate"
FROM DUAL
At least one problem is this expression in the first then clause:
CONVERT(NUMERIC(8, 2), CONVERT(VARCHAR(23), GETDATE()))
This expression:
select CONVERT(VARCHAR(23), GETDATE())
just returned:
May 23 2014 3:01AM
And that just won't convert to numeric.
I think you need to go through the code line by line to figure out the best way to do things. Also, whenever you use varchar or char, you should have a length associated with them. The default is sometimes (but not always) 1, and that can cause problems.
Oracle and SQLServer work with datetime in different manner.
The tool converted the script as well as a string parser can, like someone translating a quote word by word between two languages.
In SQLServer to work with that data type you have to use the functions DATEADD, DATEDIFF and other ones that can be found on the help page from MS.
Using the date function of SQLServer the original function translate to
CREATE PROC Dates(
#PeriodType varchar(15),
#ReportStart varchar(15),
#ReportEnd varchar(15)
)
AS
BEGIN
SELECT CASE WHEN #PeriodType = 'CUR_WEEK' THEN DATEADD(DAY, - DATEPART(dw, GETDATE()) + 1, cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'NEXT_WEEK' THEN DATEADD(DAY, 8 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'PREV_DAY' THEN DATEADD(DAY, -1, cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'PREV_WEEK' THEN DATEADD(DAY, - DATEPART(dw, GETDATE()) - 6, cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'PREV_2WEEK' THEN DATEADD(DAY, - 13, cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'CUR_MONTH' THEN DATEADD(DAY, - DATEPART(DAY, GETDATE()) + 1, cast(cast(GETDATE() AS date) AS datetime))
WHEN #PeriodType = 'DATE_RANGE' THEN CONVERT(DATETIME, #ReportStart)
END AS StartDate,
, CASE WHEN #PeriodType = 'CUR_WEEK' THEN DATEADD(mi, -1, DATEADD(DAY, 8 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime)))
WHEN #PeriodType = 'NEXT_WEEK' THEN DATEADD(mi, -1, DATEADD(DAY, 15 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime)))
WHEN #PeriodType = 'PREV_DAY' THEN DATEADD(mi, -1, DATEADD(DAY, - DATEPART(dw, GETDATE()) + 1, cast(cast(GETDATE() AS date) AS datetime)))
WHEN #PeriodType = 'PREV_WEEK' THEN DATEADD(mi, -1, DATEADD(DAY, 8 - DATEPART(dw, GETDATE()), cast(cast(GETDATE() AS date) AS datetime)))
WHEN #PeriodType = 'PREV_2WEEK' THEN DATEADD(mi, -1, cast(cast(dateadd(DAY, 1, GETDATE()) AS date) AS datetime))
WHEN #PeriodType = 'CUR_MONTH' THEN DATEADD(DAY, -1, DATEADD(mm, DATEDIFF(mm, 0, cast(cast(GETDATE() AS date) AS datetime))+1,0))
WHEN #PeriodType = 'DATE_RANGE' THEN CONVERT(DATETIME, #ReportEnd) + 1
END AS EndDate
END
The double CAST in CAST(CAST(GETDATE() AS DATE) AS DATETIME) is a little hack to get midnight of today, as GETDATE() is of datetime type and returns the current date and time.

Converting DateTime to nvarchar, just month and year

How to convert the datetime value to nvarchar and want to format it "Month, Year" e-g October 1st 2009 value should get converted to "October, 2009"
use this:
select CONVERT(nvarchar(50), DATENAME(m, getdate())
+ ', '
+ DATENAME(yyyy, getdate())
)
OUTPUT:
--------------------------------------------------
October, 2009
(1 row(s) affected)
Try this
DECLARE #DateTime DATETIME
SET #DateTime = '01 Oct 2009'
SELECT #DateTime
SELECT DATENAME(mm, #DateTime) + ', ' + CAST(DATEPART(yy, #DateTime) AS VARCHAR(4))
One way would be to use datename to extract the pieces you needed in name format, so:
select Convert(nvarchar,datename(m,getdate())) + N', ' + Convert(nvarchar,datename
(yy,getdate()))
And replace getdate() with your date variable / field.
The DateName function will provide the formatting you require:
DATENAME(m, date) + ', ' + DATENAME(yyyy, date)
Converting to nvarchar of a specific size can be done through the cast function:
CAST(value AS nvarchar[30])
Try the following query:
Select case Convert(int, day(getdate())) when 1 then '1st' when 2 then '2nd'
when 3 then '3rd' else Convert(varchar, day(getdate()))+'th' end +' '+ Convert(varchar, Datename(m,getdate()))+' ' +Convert(varchar, Datename(yy,getdate())) as Date
You can replace getdate() with any other date.
Please check if it helps.

Get only the Date part of DateTime in mssql [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Get just the Date from grouping in select from DateTime column in SQL Server
How can I get only the Date part of a DateTime ? I'm searching for something like year() function but for the whole date.
This may also help:
SELECT convert(varchar, getdate(), 100) -- mon dd yyyy hh:mmAM (or PM)
-- Oct 2 2008 11:01AM
SELECT convert(varchar, getdate(), 101) -- mm/dd/yyyy - 10/02/2008
SELECT convert(varchar, getdate(), 102) -- yyyy.mm.dd – 2008.10.02
SELECT convert(varchar, getdate(), 103) -- dd/mm/yyyy
SELECT convert(varchar, getdate(), 104) -- dd.mm.yyyy
SELECT convert(varchar, getdate(), 105) -- dd-mm-yyyy
SELECT convert(varchar, getdate(), 106) -- dd mon yyyy
SELECT convert(varchar, getdate(), 107) -- mon dd, yyyy
SELECT convert(varchar, getdate(), 108) -- hh:mm:ss
SELECT convert(varchar, getdate(), 109) -- mon dd yyyy hh:mm:ss:mmmAM (or PM)
-- Oct 2 2008 11:02:44:013AM
SELECT convert(varchar, getdate(), 110) -- mm-dd-yyyy
SELECT convert(varchar, getdate(), 111) -- yyyy/mm/dd
SELECT convert(varchar, getdate(), 112) -- yyyymmdd
SELECT convert(varchar, getdate(), 113) -- dd mon yyyy hh:mm:ss:mmm
-- 02 Oct 2008 11:02:07:577
SELECT convert(varchar, getdate(), 114) -- hh:mm:ss:mmm(24h)
SELECT convert(varchar, getdate(), 120) -- yyyy-mm-dd hh:mm:ss(24h)
SELECT convert(varchar, getdate(), 121) -- yyyy-mm-dd hh:mm:ss.mmm
SELECT convert(varchar, getdate(), 126) -- yyyy-mm-ddThh:mm:ss.mmm
-- 2008-10-02T10:52:47.513
-- SQL create different date styles with t-sql string functions
SELECT replace(convert(varchar, getdate(), 111), '/', ' ') -- yyyy mm dd
SELECT convert(varchar(7), getdate(), 126) -- yyyy-mm
SELECT right(convert(varchar, getdate(), 106), 8) -- mon yyyy
The Source
The solution you want is the one proposed here:
https://stackoverflow.com/a/542802/50776
Basically, you do this:
cast(floor(cast(#dateVariable as float)) as datetime)
There is a function definition in the link which will allow you to consolidate the functionality and call it anywhere (instead of having to remember it) if you wish.
Another nifty way is:
DATEADD(dd, 0, DATEDIFF(dd, 0, [YourDate]))
Which gets the number of days from DAY 0 to YourDate and the adds it to DAY 0 to set the baseline again. This method (or "derivatives" hereof) can be used for a bunch of other date manipulation.
Edit - other date calculations:
First Day of Month:
DATEADD(mm, DATEDIFF(mm, 0, getdate()), 0)
First Day of the Year:
DATEADD(yy, DATEDIFF(yy, 0, getdate()), 0)
First Day of the Quarter:
DATEADD(qq, DATEDIFF(qq, 0, getdate()), 0)
Last Day of Prior Month:
DATEADD(ms, -3, DATEADD(mm, DATEDIFF(mm, 0, getdate()), 0))
Last Day of Current Month:
DATEADD(ms, -3, DATEADD(mm, DATEDIFF(m, 0, getdate()) + 1, 0))
Last Day of Current Year:
DATEADD(ms, -3, DATEADD(yy, DATEDIFF(yy, 0, getdate()) + 1, 0))
First Monday of the Month:
DATEADD(wk, DATEDIFF(wk, 0, DATEADD(dd, 6 - DATEPART(day, getdate()), getdate())), 0)
Edit:
True, Joe, it does not add it to DAY 0, it adds 0 (days) to the number of days which basically just converts it back to a datetime.
We can use this method:
CONVERT(VARCHAR(10), GETDATE(), 120)
Last parameter changes the format to only to get time or date in specific formats.
This may not be as slick as a one-liner, but I use it to perform date manipulation mainly for reports:
DECLARE #Date datetime
SET #Date = GETDATE()
-- Set all time components to zero
SET #Date = DATEADD(ms, -DATEPART(ms, #Date), #Date) -- milliseconds = 0
SET #Date = DATEADD(ss, -DATEPART(ss, #Date), #Date) -- seconds = 0
SET #Date = DATEADD(mi, -DATEPART(mi, #Date), #Date) -- minutes = 0
SET #Date = DATEADD(hh, -DATEPART(hh, #Date), #Date) -- hours = 0
-- Extra manipulation for month and year
SET #Date = DATEADD(dd, -DATEPART(dd, #Date) + 1, #Date) -- day = 1
SET #Date = DATEADD(mm, -DATEPART(mm, #Date) + 1, #Date) -- month = 1
I use this to get hourly, daily, monthly, and yearly dates used for reporting and performance indicators, etc.

Resources