I need to run a SQL script every night that extracts data from the previous 2 days. For example: On July 9 at 1am, the script runs and needs to extract data from July 8 and July 7. On July 10 at 1am, it needs to extract data from July 9 and July 8, etc.
The script is functional, in that it correctly extracts data for a fixed date range (by including the actual date range in the script), but I don't know how to make it do the "2 days prior" part.
Figuring this out is beyond me! Can anyone provide guidance?
Using SQL Server 2014
You can do:
where datecol >= convert(date, dateadd(day, -2, getdate())) and
datecol < convert(date, getdate())
That said, I would be very wary about putting this logic directly into a query. I would create a stored procedure in SQL Server and have it take #fromdate and #todate arguments.
Then, schedule a job that does the above calculation and calls the stored procedure with the right parameters.
One day, when the server is down or the logic fails, you will appreciate having the flexibility to specify the date range yourself.
I would create three variables.
#today: is the current datetime cast to a date to set it to midnight
#startDate: first/start date where I would use the DATEADD function to subtract two days
#endDate: end date that you can subtract 1 second from today
This should get you a date range of 2019-07-07 00:00:00.000 to 2019-07-08 23:59:59.000
DECLARE #today DATETIME = CAST(GETDATE() AS DATE);
DECLARE #startDate DATETIME = DATEADD(DAY, -2, #today);
DECLARE #endDate DATETIME = DATEADD(SECOND, -1, #today);
Time is usually very critical when working with dates, make sure your start date starts at the beginning of the day and your end date ends at the very end of the day!
Your query would then look like:
SELECT *
FROM my_table
WHERE my_date_column BETWEEN #startDate AND #endDate
Related
This is what my query's date range is:
WHERE
date BETWEEN 20190101 AND [here date should come as last year YTD -1]
For example if we use this query today (20201106) (format:yyyymmdd), then the 2nd date should be 20191105.
For more clarity: when I run this query today (20201106) my query should fetch results from date range:
WHERE
date BETWEEN 20190101 AND 20191105
When I run this query tomorrow (20201107), my query should fetch results from the date range:
WHERE
date BETWEEN 20190101 AND 20191106
How can I do this?
Can anyone help?
you can use dateadd() with getdate()
DATEADD(year,-1, GETDATE())
or other function that can get current database time but this should work.
also remember to use convert() to modify the date format into what you want.
WHERE
DATEADD(YEAR,-1, GETDATE()) -- One Day Before Today in the Last Year
AND
DATEADD(yy, DATEDIFF(yy, 0, DATEADD(YEAR,-1, GETDATE())), 0) AS StartOfYear -- The Day 1 of the Last Year
I would phrase this as:
where date >= datefromparts(year(getdate()) - 1, 1, 1)
and date < dateadd(year, -1, convert(date, getdate()))
This filters from the start of last year and the 1 year and 1 day ago.
Note that I changed the filtering strategy to use half-open intervals rather than between. This is somehow more flexible, as it would properly handle a time component in in date, if any, and simplifies the offsetting logic.
Note also that getdate() has a time component, that needs to be removed while offsetting to implement your logic.
I have a task that I need to show the current date time as ending at 3:00:00 AM at current date. For example, GETDATE() returns the current date time when executes. I need to show it as 9/5/2019 3:00:00 AM instead. Below is my code:
DECLARE #END_SHIFT AS DATETIME
SET #END_SHIFT = '06:00:00 AM'
SELECT
NUMBER_ID,
GETDATE() AS CURRENT_DT,
GETDATE() - #END_SHIFT AS END_SHIFT_DATE
FROM table
My issue when running this is it does not return as ending at 3:00:00AM. Please let me know your direction.
Thanks,
H
A bit of an odd request for sure but you could simply use DATEADD.
SELECT dateadd(hour, 3, convert(datetime, convert(date, getdate())))
If you really need a "hard" time, one option is to use format()
Example
Select format(GetDate(),'yyyy-MM-dd 03:00')
Returns
2019-09-05 03:00
I am a complete noob to SQL and trying to understand why this query returns "115":
select datediff(yy, -3, getdate())
datediff takes three Parameter. The first is the interval, the second the start date and the third the end date. You are passing -3 as start date, there we can show:
SELECT CAST(-3 AS datetime) -- results in '1899-12-29 00:00:00.000'
And because 2014 - 1899 is 115, you will get this as result.
Because DATEDIFF() calculates an interval between 2 dates, and you specified year -3 in one of them.
Firstly, the date "zero" is 12/30/1899 on SQL server.
Secondly, your "-3" was an incorrect date format and it thus replaced it with its 0
2014 - 1899 = 115
Use DATEADD() instead to achieve what you want to do.
DateDiff gives difference in years/date/months etc based on what you have given in first parameter. second and third parameter are datetime values which will be used to calculate the difference i.e. (param2 datetime value - param3 datetime value).
Now in your case param2 is "-3"
run this queries in you ms sql and observe the outputs :
select CAST(-3 as datetime)
select GETDATE()
select datediff(yy, -3, getdate())
What I am trying to do is to see if a datetime variable has the value of a date at anytime in the past twelve months.
I tried using the DATEDIFF function but then I quickly discovered that this has rounding problems (a comparison between 31st DEC/1st JAN would count as 1 month for example, despite the fact only a day has passed between them)
To make this more accurate I could use -365 days as a parameter rather than -12 months however this still gives the problem of not taking into account leap years (not a common scenario but still one I'd ideally avoid!)
Any ideas as to how I can best go about this?
The problem with leap years can be solved with the DATEADD (datepart , number , date ) function. You can specify minus one year from the current date.
where myDate between DATEADD (year , -1 , GETDATE() ) and GETDATE()
Use DATEADD instead to subtract a year from today and compare that
#datetimevariable >= DATEADD(year, -1, GETDATE())
Note: you don't need to compare the upper bound (GETDATE()) unless you have dates in the future.
Also, do you want exactly one year down to the hour and minute? If not, use this which is safe for datatype precedence if #datetimevariable is datetime or datetime2, and you need this is a WHERE clause or such
#datetimevariable >= CAST(DATEADD(year, -1, GETDATE()) as date)
This works for leap years
SELECT DATEADD(YEAR, -1, '20120301'), DATEADD(YEAR, -1, '20120229')
2011-03-01 00:00:00.000
2011-02-28 00:00:00.000
DATEDIFF works on specific boundary: start of month, start of year, midnight etc which is why it fails in this case
DATEDIFF counts the number of partitions between the two dates, sorry to say there is no rounding issue, it does exactly what it says on the tin. YOUR best solution is probably to used DATEADD
WHERE MyVal BETWEEN GETDATE() AND DATEADD(YEAR, -1, GETDATE())
I've referred to this on MSDN but I'm still unsure what the second argument in the DATEDIFF function is doing in the following two examples:
SELECT DATEDIFF(yy,0,getdate()) --run on 14 Aug this returns 112
SELECT DATEDIFF(yy,1000,getdate()) --I chose 1000 arbitrarily and run on 14 Aug this returns 110
Usually I'll use DATEDIFF to find the number of days, or number of years between two months and the second argument is then a date.
Reason I'd like to understand the above is to ultimately understand the following:
SELECT DATEADD(yy, DATEDIFF(yy,0,GETDATE()), 0)
If you use an integer as the second argument (or for any datetime/smalldatetime assignment for that matter), this is interpreted as the number of days since 1900-01-01.
DECLARE #d1 DATETIME = 0, #d2 DATETIME = 1;
SELECT #d1, #d2;
Result:
1900-01-01 00:00:00.000 1900-01-02 00:00:00.000
Note that this doesn't work for new data types like DATE during direct assignment:
DECLARE #d DATE = 0;
Result:
Msg 206, Level 16, State 2, Line 1
Operand type clash: int is incompatible with date
But it can still work using date math, e.g.:
DECLARE #d DATE = DATEADD(YEAR, 0, SYSDATETIME());
SELECT #d;
Result:
2012-08-14
For these inconsistent reasons, I recommend you use proper date literals so that it is clear which date you mean and so that it works regardless of the data type. This is a habit I find hard to break, since typing 0 is so much easier than 19000101...
Consider below example to understand this concept better. 0 is default date "1900-01-01"
Below Query gives output as 2017-10-31 00:00:00.000
SELECT DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH,0,SYSDATETIME())+3, 0))
Dividing the above query into various parts to understand the calculation.
-- 1414 Months since '1900-01-01'
SELECT DATEDIFF(MONTH,0,SYSDATETIME()) + 3
-- adding 1414 Months to Default date 1900 Produces '2017-11-01 00:00:00.000'
SELECT DATEADD(MONTH, DATEDIFF(MONTH,0,SYSDATETIME())+3, 0)
--Subtract 1 day from '2017-11-01 00:00:00:000' gives last day of previous month.
SELECT DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH,0,SYSDATETIME())+3, 0))
The second argument to datediff() is a date.
The first example returns the "start" date of time in the SQL Server world. That would be 112 years before the current date.
The second example is rather non-sensical. As implemented, the dates are represented as number days since the earliest date. This is the number of years since 1000 days after the earliest date.
The last example adds a number of years to the base date. It then adds a number of months. Since the base date is 1/1/1900, this is giving you the first date of the day after the nth month in the yth year.