Alternative for T-SQL on date calculation for where clause - sql

I have a SQL data calculation which is used as part of where clause to get bookings from calculated date at midnight.
My solution:
bookDate >= (SELECT DATEADD(dd, -7, DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)))
The original was:
bookDate >= DATEADD(dd, -7, GETDATE())
However it returns at calculated date + current time
Is there a alternative and far simpler approach to this?

This is a bit simpler.
bookDate >= DATEADD(dd, DATEDIFF(dd, 0, GETDATE()) - 7, 0)
In SQL Server 2008 and SQL Server 2012 you can use the date data type.
bookDate >= DATEADD(dd, -7, CAST(GETDATE() as DATE))

The following will also work for 2005:
SELECT DATEADD(dd, -7, FLOOR(CAST(GETDATE() AS FLOAT)))
This works because SQL Server (and windows, for that matter) stores a date as a floating point, with the whole number representing the number of days is 01/01/1900, and the fraction part representing the time. The following is shorter, and more consistent with what I usually use in this situation:
SELECT FLOOR(CAST(GETDATE() AS FLOAT) -7)
DATEADD is useful if you're calculating on something other than days (i.e. months, years), because of the varying number of days is each given month or year. When working with days, it's often easier to add or subtract directly. Similarly, if you wanted to subtract, for example, two hours from a date, you can use:
SELECT CAST(GETDATE() AS FLOAT) * 2.0/24.0

You could also do it like this:
bookDate >= CAST(CONVERT(char(8), GETDATE() ,112) as datetime)

Related

How to go back two days from a date in sql?

I wrote an SQL query that allows me to get the sales of certain stores.
My query runs every mornings and I would like to get the sales from 2 days ago at runtime.
For example if my query runs tomorrow morning, on 08/12, I would like to have the sales whose value in the column "GP_HEURECREATION" starts with "20200612", to have all the sales of the whole day.
The GP_HEURECREATION column has a format like this: "20200612 00:00:00" and is of the DATE type.
I tried with NOW() and DATEADD() but I have 2018 values that stand out for example.
How can I get the values only two days before the query is executed?
SELECT
T_ETABLISSEMENT, ET1.ET_LIBELLE AS C1, GL_ETABLISSEMENT,
GP_HEURECREATION, GP_REFINTERNE, GL_CODEARTICLE,
LIBDIM2, LIBDIM1, GL_QTEFACT, GL_PUTTC,
(GL_TOTALHT * GP_COTATIONDOS) AS TOTALHTDEV, GL_DPR, GL_DEVISE,
GL_NATUREPIECEG, GA_LIBELLE
FROM
GCLIGNEARTDIM
LEFT OUTER JOIN
PGI_LOOKUP(TTETABLISSEMENT) ET1 ON GL_ETABLISSEMENT = ET1.ET_ETABLISSEMENT
WHERE
(GP_HEURECREATION <= DATEADD(day, -2, GETDATE())
AND (GL_NATUREPIECEG = "FFO")
AND GL_ETABLISSEMENT = "20897", "10519", "20267", "26451", "20269", "26078", "28047", "20900", "28085", "24984", "27113", "20268", "19994", "28450", "26876", "24063", "18066", "3220"
ORDER BY
GP_REFINTERNE
The syntax of your existing query suggests SQL Server. If you want records that belong to day -2, you can do:
where gp_heurecreation >= dateadd(day, -2, convert(date, getdate()))
and gp_heurecreation < dateadd(day, -1, convert(date, getdate()))
If gp_heurecreation has no time component (in SQL Server, that's a date datatype), this is simpler:
where gp_heurecreation = dateadd(day, -2, convert(date, getdate()))

get the first n characters of getdate()

I have a case compare date, hour of datetime column and current date,hour
select * from tbl where LEFT(EVENT_TIME_column,13) !=LEFT(GETDATE(),13)
EVENT_TIME_column format is '2019-08-15 12:32:40.0000000'
when i perform LEFT(GETDATE(),13) result is 'Aug 15 2019'
can you suggest how to get GETDate() in '2019-08-15 12' (date and hour)
If you want the format yyyy-MM-dd hh then can do this:
SELECT CONVERT(varchar(13),GETDATE(),120);
db<>fiddle
You can find a full list of all the style codes for CONVERT in the documentation: Date and Time Styles
However, it looks like you want to check if the date is within the current hour. That would be:
WHERE EVENT_TIME_column >= DATEADD(HOUR, DATEDIFF(HOUR, 0,GETDATE()),0)
AND EVENT_TIME_column < DATEADD(HOUR, DATEDIFF(HOUR, 0,GETDATE())+1, 0)
This explicitly avoids any functions on the column EVENT_TIME_column; which would make the query non-SARGable.
Don't use string functions on date/time values! There are perfectly good built-in functions:
where convert(date, event_time_column) = convert(date, getdate()) and
datepart(hour, event_time_column) = datepart(hour, getdate())
If you don't care about index usage, then use datediff():
where datediff(hour, event_time_column, getdate()) = 0
You can check this with 2 separate comparison as below. This is for checking Date and Hour part is same as date and hour part if GETDATE() or not.
WHERE CAST(EVENT_TIME_column AS DATE) = CAST(GETDATE() AS DATE)
AND DATEPART(HH,EVENT_TIME_column) = DATEPART(HH,GETDATE())
To check NOT EQUAL TO, Just replace = sign with != sign.
In addition, If I guess correct you are only trying to avoid records from running hour of to date. If this is the case, you can also filter your data with below logic-
WHERE EVENT_TIME_column < DATEADD(hh, DATEDIFF(hh, 0, getdate()), 0)

SQL- Weekly report seven days (Sunday to Saturday )

I have created the following query to reoccur every seven days starting including Saturday and Sunday. This report will be run every seven days. However, the problem I am facing on the days where there were files received in our SFTP folder (inbound) report should have an entry for the missing Null= 0. The primary goal to make this an automated process that will be executed every Sunday through Sunday every seven days
Example:
SELECT SubmitterID,SubmitterName,convert(varchar(15), DateReceived, 101) DateReceived,sum(ClaimCount) as TotalCount
FROM FalloutClaimReport
WHERE DateReceived BETWEEN '2019-06-01' AND '2019-06-07'
--ORDER BY COUNT(submitterID) DESC;
GROUP BY submitterid, SubmitterName, convert(varchar(15), DateReceived, 101)
DECLARE #StartDate AS DATETIME
DECLARE #EndDate AS DATETIME
DECLARE #CurrentDate AS DATETIME
SET #StartDate = '2019-06-01' --AND '2019-06-10'
SET #StartDate = '2019-06-07'
SET #EndDate = GETDATE()
SET #CurrentDate = #StartDate
I'm a little uncertain what you're looking for but I think the general approach is you're trying to get a week's worth of data.
Date calculations
Let's start with some queries (and these presume a US install as the default day is Monday.
SELECT
DATEADD(WEEK, -1, CAST(DATEADD(WEEK, DATEDIFF(WEEK, 0, CAST(GETDATE() AS date)), -1) AS date)) AS TheLastSundayOfTheFullWeek
, DATEADD(WEEK, -1, CAST(DATEADD(WEEK, DATEDIFF(WEEK, 0, CAST(GETDATE() AS date)), +5) AS date)) AS TheLastSaturdayOfTheFullWeek
, CAST(DATEADD(WEEK, DATEDIFF(WEEK, 0, CAST(GETDATE() AS date)), -1) AS date) AS SundayOfTheCurrentWeek
, CAST(DATEADD(WEEK, DATEDIFF(WEEK, 0, CAST(GETDATE() AS date)), +5) AS date) AS SaturdayOfTheCurrentWeek;
These queries generate the following dates
TheLastSundayOfTheFullWeek TheLastSaturdayOfTheFullWeek SundayOfTheCurrentWeek SaturdayOfTheCurrentWeek
2019-06-30 2019-07-06 2019-07-07 2019-07-13
The last full week would run 6/30 to 7/06. The current week would be defined as 7/7 to 7/13.
Depending on which week definition you need, choose the appropriate pair of columns.
Dealing with the unknowns
In situations like this, I build out a virtual table with all expected dates (or elements) my report should have. I then use that to drive a connection to the actual data table. Since we don't know that we'll find any rows for a given date, I connect the tables with a LEFT JOIN
SELECT
FCR.SubmitterID
, FCR.SubmitterName
, CONVERT(varchar(15), ED.DateReceived, 101) AS DateReceived
, SUM(FCR.ClaimCount) AS TotalCount
FROM
(
-- This logic builds out a list of all the dates that must exist on the report
-- I used the logic for TheLastSundayOfTheFullWeek
SELECT
DATEADD(DAY, D.DayOffset, DATEADD(WEEK, -1, CAST(DATEADD(WEEK, DATEDIFF(WEEK, 0, CAST(GETDATE() AS date)), -1) AS date))) AS DateReceived
FROM
(
-- Generate a series of 7 numbers from 0 t 6
SELECT TOP 7
-1 + ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rn
FROM
sys.all_columns AS AC
) D(DayOffset)
) AS ED
LEFT OUTER JOIN
dbo.FalloutClaimReport AS FCR
ON FCR.DateReceived = ED.DateReceived
GROUP BY
CONVERT(varchar(15), ED.DateReceived, 101)
, FCR.SubmitterID
, FCR.SubmitterName;
That generates a result set like
We didn't have data on the the 30th or the 5th but there are still records on the query. If you need default values in there, wrap the column with ISNULL/COALESCE calls.
DBFiddle version to provide a testing sandbox
Audrey,
I would suggest two possible solutions. Assuming by SRS you meant, SSRS....
1) I would set your SSIS job to run through a SQL Agent every 7 days. It would call a stored procedure (SP) that then ran and wrote into a table... when that SP would be called it would run:
SELECT
SubmitterID,
SubmitterName,
convert(varchar(15), DateReceived, 101) DateReceived,
sum(ClaimCount) as TotalCount
FROM FalloutClaimReport
WHERE cast(DateReceived as date) BETWEEN dateadd(d,-7,cast(getdate() as date)) AND dateadd(d,-1,cast(getdate() as date))
GROUP BY
submitterid,
SubmitterName,
convert(varchar(15), DateReceived, 101)
2) If you decide to go the SSRS route, you should make a report subscription that sends automatically to the users you need that calls the stored procedure above and sends what you need to whoever needs it. (The code above should be enough for that assuming it's selecting what you need)

Keyword for "Last Month" in SQL Server 2008

I have a query (pasted below), and I would like to make it so that people don't need to update the completed date range. I would like for it to automatically just get results from last month. So if it is run in February, for example, it will give me results for all completed items that meet my criteria for January. Can anyone think of a way to do that?
select External_ID__c,
Ewrk_Tracking_Number__c,
PIF_Branch_Name,
Distribution_Branch_Name,
Transaction_Type__C,
submitter_date__c, Completed_Date__C,
COUNT(External_ID__c)
from Business_Solutions_D.dbo.Reporting_SalesForce_AspireBaseData
where PIF_Branch_Code = 977
and Completed_Date__C >= '2015-01-01'
and Completed_Date__C < '2015-02-01'
and Delete_Flag__C = 'FALSE'
group by External_ID__c,
Ewrk_Tracking_Number__c,
PIF_Branch_Name,
Distribution_Branch_Name,
Transaction_Type__C,
submitter_date__c,
Completed_Date__C
There is no "keyword" for last month. You have to put that in your predicates.
Here is an example of how to get some date values for this.
select dateadd(MONTH, datediff(MONTH, 0, GETDATE()), 0) as BeginningOfThisMonth
select dateadd(MONTH, datediff(MONTH, 0, GETDATE()) - 1, 0) as BeginningOfPreviousMonth
If you want to see a number of other date routines here is an excellent blog post with quite a few of them. http://www.sqlservercentral.com/blogs/lynnpettis/2009/03/25/some-common-date-routines/
If you mean the last month prior to this one, you can do it in two steps: first, find the first day of the current month
#firstDayOfThisMonth = DATEADD(day, DAY(GETDATE())-1, GETDATE())
then subtract one month:
#firstDayOfLastMonth = DATEADD(month, -1, #firstDayOfThisMonth)
Then your query would be:
and Completed_Date__C >= #firstDayOfLastMonth
and Completed_Date__C < #firstDayOfThisMonth
Another way would be to query where the difference (in months) between Completed_Date__C and the current date is 1:
and DATEDIFF(Completed_Date__C, GETDATE()) = 1
You can do this with date arithmetic. One trick to get the first date of the month is to subtract the current day of the month from the date and add one day. SQL Server allows you to do this with + and - instead of dateadd(), on a datetime value. Of course, you need to remove the time component as well (using cast( as date)).
The logic looks like this for the current month:
where Completed_Date__C >= cast(getdate() - day(getdate()) + 1 as date) and
Completed_Date__C < dateadd(month, 1, cast(getdate() - day(getdate()) + 1 as date))
And like this for the previous month:
where Completed_Date__C >= dateadd(month, -1, cast(getdate() - day(getdate()) + 1 as date)) and
Completed_Date__C < cast(getdate() - day(getdate()) + 1 as date)
This has the nice property that it is a sargeable as your original code, so it will take advantage of an index on the column, if appropriate.
You just need to have it do some date math to calculate it.
--Go to last day of prev month - 'Day' to account for varying month day counts
and Completed_Date__C >= GETDATE() - DATEPART(DAY, GETDATE()) - DATEPART(DAY, GETDATE() - DATEPART(DAY, GETDATE())) + 1
and Completed_Date__C < GETDATE() - DATEPART(DAY, GETDATE()) + 1
When you do additions on DateTimes + integer it assumes it day based addition.

Weekly to Monthly Reports

I was running weekly reports as in the below script. However, I now want to run monthly report so needed some assistance.
Weekly:
SELECT * FROM TABLE WHERE
(ARRIVAL_DATE>GETDATE()-7)//7 days before
AND
(ARRIVAL_DATE<GETDATE()) //NOW
For monthly report, will below script be right if I run on every 1st?
SELECT Column1,...
FROM TableName
WHERE
MONTH(DateColumn) = MONTH(dateadd(dd, -1, GetDate()))
AND
YEAR(DateColumn) = YEAR(dateadd(dd, -1, GetDate()))
Thanks.
Your logic looks okay, although I would use day instead of dd, because I think it is clearer.
However, your query will prevent the use of an index on datecolumn. The following is a "better" form of the logic, because it allows the use of an index:
where datecolumn >= dateadd(month, -1,
dateadd(day, 1 - day(getdate()), cast(getdate() as date))
) and
datecolumn < dateadd(day, 1 - day(getdate()), cast(getdate() as date))
This looks more complicated, but all the functions are on getdate(), so the engine can use an index. Also note the explicit conversion to date. getdate() returns a time component which might throw off the logic if datecolumn only has a date.
where datecolumn between dateadd(mm, -1,getdate()) and getdate()