I found the following
Select dateadd(minute, datediff(minute,0,GETDATE()) / 15 * 15, 0)
which is great for rounding to the last quarter of the hour. But I would like to always get the last quarter of the last hour.
e.g.,
If time is 12:35 am I want to see 11:45 am since that is the last quarter of the hour.
You can use datetimefromparts():
select datetimefromparts(year(dt), month(dt), day(dt), datepart(hour, dt), 45, 0, 0)
from (values (dateadd(hour, -1, getdate()))) v(dt);
This is a bit long winded, just the way my mind works (Gordan's is far more succinct that mine):
DECLARE #time time = '12:35'
SELECT CONVERT(time,DATEADD(MINUTE,45,DATEADD(HOUR, DATEDIFF(HOUR,'00:00',DATEADD(MINUTE, -45, #time)),'00:00')));
Assuming I understand the question, you want to get the current hour of the current minute is between 45 and 59, or the previous hour if the current minute is between 0 and 44 - So here is my suggested solution:
DECLARE #ActualTime DateTime = GetDate()
SELECT #ActualTime As ActualTime, DATETIMEFROMPARTS(YEAR(Now), MONTH(Now), DAY(Now), DATEPART(HOUR, Now), 45, 0, 0) As LastQuarterOfHour
FROM
(
SELECT IIF(DATEPART(MINUTE,#ActualTime) < 45, DATEADD(HOUR, -1, #ActualTime), #ActualTime) As Now
) AS x
Related
I have a complex (complex because it gave me lots of work to complete!) and it returns results that fulfill the query till the day 30 of the current month.
Here is the code:
SELECT
CONCAT(' ', CONVERT(date, fc.dataven), ' '),
fc.adoc, fc.nome,
CONCAT(CONVERT(money, fc.ecred), ' €')
FROM
fc, fl
WHERE
dataven BETWEEN DATEFROMPARTS(IIF(MONTH(GETDATE()) = 1, YEAR(GETDATE())-1, YEAR(GETDATE())),
IIF(MONTH(GETDATE()) = 1, 12, MONTH(GETDATE()) - 1), 30)
AND CAST(DATEADD(day,-day(GETDATE()),DATEADD(month, 1,GETDATE())) as DATE)
AND fc.adoc NOT LIKE ''
AND fc.cmdesc LIKE 'v%'
AND fc.evalpo = '0'
AND (fc.cmdesc LIKE '%factura%' OR fc.cmdesc LIKE '%cred%')
AND fc.nome = fl.nome
AND fl.pais LIKE 1
GROUP BY
fc.adoc, fc.dataven, fc.nome, fc.ecred
ORDER BY
fc.nome
I have a job that runs this query on the third monday of every month.
What i need is that the query returns values not only till the 30th day of the current month but till the 10th day of the next month.
I'm a bit lost, can anyone give me a hint please?
I would phrase the where predicate as:
dataven between eomonth(getdate()) and dateadd(day, 11, eomonth(getdate()))
This filters on dates between the last day of the current month and the 10th day of next month. This is not exactly what you ask for, but it seems like a reasonable way to address the question - not all months have exactly 30 days (actually, there are just 4 months in the year that have 30 days).
Edit
From the comments:
I need the query to work between the day 25 of the prior month till the day 10 of the next month
That's not the same thing. You can phrase this as:
where dataven
between dateadd(day, 24, dateadd(month, -1, datefromparts(year(getdate()), month(getdate()), 1)))
and dateadd(day, 9, dateadd(month, 1, datefromparts(year(getdate()), month(getdate()), 1)))
This assumes that dataven has no time component. Otherwise, you probably would prefer:
where dataven >= dateadd(day, 24, dateadd(month, -1, datefromparts(year(getdate()), month(getdate()), 1)))
and dataven < dateadd(day, 10, dateadd(month, 1, datefromparts(year(getdate()), month(getdate()), 1)))
It seems the shortest way would be to use EOMONTH function
dataven between dateadd(day, -5, eomonth(getdate(), -1))
and dateadd(day, 10, eomonth(getdate(), 0))
I would perform the expressions outside of the query because they are much easier to test and debug that way, and they keep your query cleaner and easier to maintain as well.
DECLARE #lastmonth date = DATEADD(MONTH, -1, sysdatetime());
DECLARE #nextmonth date = DATEADD(MONTH, 2, #lastmonth);
DECLARE #start date = DATEFROMPARTS(YEAR(#lastmonth), MONTH(#lastmonth), 25),
#end date = DATEFROMPARTS(YEAR(#nextmonth), MONTH(#nextmonth), 11);
SELECT
...
FROM dbo.fc INNER JOIN dbo.fl
ON fc.nome = fl.nome
WHERE dataven >= #start AND dataven < #end
...
Some further reading:
What do BETWEEN and the devil have in common
Simplify date period calculations
Bad Habits to Kick : Avoiding the schema prefix
Bad Habits to Kick : Using old-style JOINs
MS SQL Server: I'm trying to get 7 days after the end of the last quarter...
Here's what I have so far.
DATEADD(D, 0, DATEDIFF(D, 0, DATEADD(s,-1,DATEADD(q, 1, DATEADD(q, DATEDIFF(q, 0, GETDATE()) - 1, 0))))) AS LastDayOfLastFullQuarter
Your original expression was close (you needed to add 7 days, not 0):
------------------v
SELECT DATEADD(D, 7, DATEDIFF(D, 0, DATEADD(s,-1,DATEADD(q, 1, DATEADD(q, DATEDIFF(q, 0, GETDATE()) - 1, 0))))) AS SevenDaysAfterLastDayOfLastFullQuarter
But, good gravy, that's hard to read, and not just because of all the shorthand. Generally, it is better to find the beginning of the next period than the end of the current one. Subtracting a second from the beginning of this quarter won't always get you a date/time value in the previous quarter because some types round up.
Why not think about it as calculating 6 days after the beginning of the current quarter?
DECLARE #d date = GETDATE();
SELECT DATEADD(DAY, 6,
DATEFROMPARTS
(
YEAR(#d),
MONTH(#d)-((MONTH(#d)-1)%3),
1
)
);
Another way that is more like Steve's, if you don't like all the math:
DECLARE #d date = DATEADD(QUARTER,DATEDIFF(QUARTER,'20000101',GETDATE()),'20000101');
SELECT DATEADD(DAY, 6, #d);
I talk about both of these approaches here, and unfortunately the beginning of a quarter is not a calculation that's easy to write in a self-documenting way in T-SQL, so you get to choose between unintuitive methods (dateadd/datediff from some irrelevant date, or modulo and other math), and it gets more complicated if your fiscal calendar does not align with your cute dogs of 2020 calendar:
Simplify Date Period Calculations in SQL Server
But having thought on it a moment, this approach is only a few more characters but is a little more self-documenting without the modulo and other calculations:
DECLARE #d date = GETDATE();
SELECT DATEADD(DAY, 6,
DATEFROMPARTS
(
YEAR(#d),
CASE WHEN MONTH(#d) < 4 THEN 1 -- if Jan-Mar, want Jan
WHEN MONTH(#d) < 7 THEN 4 -- if Apr-Jun, want Jun
WHEN MONTH(#d) < 10 THEN 7 -- if Jul-Sep, want Jul
ELSE 10 -- if Oct-Dec, want Oct
END,
1
)
);
I talk about why you should spell out date-related values (e.g. don't use q and d and s and 0, though the last one is still a bad habit of mine) here:
Bad Habits to Kick : Using shorthand with date/time operations
Date Shorthand
And why you should always think about the beginnings instead of the ends of periods here:
What do BETWEEN and the devil have in common?
Do Not Use BETWEEN with Dates
This should do it too
select cast(dateadd(d, 7, dateadd(qq, datediff(qq, 0, getdate()), -1)) as date);
Results
2020-07-07
declare #date datetime = getdate();
select DATEADD(d, 6, DATEFROMPARTS(YEAR(#date), (MONTH(#date) - 1) / 3 * 3 + 1 , 1))
I would use:
select dateadd(month,
-2,
datefromparts(year(getdate()), ((month(getdate()) + 2) / 3) * 3, 7)
)
I am trying to get a smalldatetime value of "9pm today" in a query. I thought I could use
DATEADD(HOUR, 21, CONVERT(date, GETDATE()))
but SQL Server doesn't like that - I get the error
The datepart hour is not supported by date function dateadd for data
type date.
Suggestions for a workaround?
Pretty simple, just cast date back to datetime after casting to date.
Thus you'll get current_date 00:00:00 and then add 21 hours:
select dateadd(hh, 21, cast(cast(getdate() as date) as datetime))
it is because dateadd's 3rd parameter should be datetime type, not date.
SELECT DATEADD(HOUR, 21, CONVERT(datetime,CONVERT(date, GETDATE())))
just add 21 / 24.0 to todays date
Select dateadd(day, datediff(day, 1, getDate()), 1) + (21 / 24.0)
First part, dateadd(day, datediff(day, 1, getDate()), 1), strips time from getdate(),
second part, + (21 / 24.0), adds fractional part of day equal to 9 am
This works because internally, SQL Server represents datetimes as two integers, one for the date, (number of days since 1 Jan 1900), and a second integer for the time, (number of ticks since midnight), which it combines into a decimal value where the integer part is the date integer, and the decimal part is the fraction of one day, so if you add 0.5 to a date, you get noon on that day, etc.
or, for comparison, using dateadd for hours,
Select dateadd(hour, 21, dateadd(day, datediff(day, 1, getDate()), 1))
How can I add hours and minutes in a single query?
I tried this
Select DATEADD(hh,23.59,CAST('2016-07-08' AS DATETIME))
I need to ad 23 hours and 59 minutes, but my code only adds the hours. Why?
How about this?
Select DATEADD(minute, 23*60 + 59, CAST('2016-07-08' AS DATETIME))
EDIT:
If you are getting a float/decimal value such as 23.59, then you can do:
Select DATEADD(minute, FLOOR(#hhmm) * 60 + (#hhmm - FLOOR(#hhmm)) * 100, CAST('2016-07-08' AS DATETIME))
Note: You can also use:
Select DATEADD(minute, FLOOR(#hhmm) * 60 + (#hhmm % 1) * 100, CAST('2016-07-08' AS DATETIME))
But I find this usage of the modulo operator slightly off-kilter.
Use the below code for adding time part to a date.
SELECT DATEADD(Day, DATEDIFF(Day, 0, CAST('2016-07-08' AS DATETIME)), '23:59:00.000')
You can also use DATEADD() twice:
Select DATEADD(minute,59,DATEADD(hh,23,CAST('2016-07-08' AS DATETIME)))
The datepart argument, in your case hh, is part of date to which an integer number is added. So the DATEADD function just ignores any fractional part of your input.
To get result you want, you need to either use DATEADD twice, adding 23 hours and then 59 minutes, or add one day to your date and subtract 1 minute, like this:
Select DATEADD(MI, -1, CAST('2016-07-08' AS DATETIME) + 1)
See also Microsoft's documentation on DATEADD.
another method : you can do by adding one day and then substract minute
Output is same
select DATEADD(minute, -1, DATEADD(DAY, 1,CAST('2016-07-08' AS DATETIME)))
I have table1 with with the columns DATETIME, ID and Status.
I will call my stored procedure after specific hours and I want to fetch records of last 48 non weekend hours.
I tried to do it by writing case for each day of getdate().
I want to know what is the best way to do this.
To avoid weekends, you can use a case or other logic in the where. Your logic isn't 100% clear on what to do on weekend days. But here is an approach:
where (datename(wk, getdate()) in ('Sunday', 'Monday', 'Tuesday') and datetime >= dateadd(hour, 48 + 48, getdate()) ) or
(datename, wk, getdate()) in ('Wednesday', 'Thursday', 'Friday') and datetime >= dateadd(hour, 48, getdate()) or
(datename , wk, getdate()) in ('Saturday') and datetime >= dateadd(hour, 24 + 48, getdate());