Getting rows between date range is not working in SQL Server - sql

In SQL Server 2008R2 fetching data between two dates is not working.
I am using the following code to get rows from the INVOICE table where the CREATED_DATE is between #startdate and #enddate, which are the parameters I am sending to the stored procedure.
Select *
from INVOICES INV
where CONVERT(Varchar(10), INV.CREATED_DATE, 105)
BETWEEN CONVERT(VARCHAR(10), #startdate, 105)
AND CONVERT(VARCHAR(10), #enddate, 105)
It is not working properly, driving me nuts..
What I am doing wrong?..

select * from
invoices inv
where inv.created_date >= dateadd(dd, 0, datediff(dd, 0, #startdate))
and inv.created_date < dateadd(dd, 1, datediff(dd, 0, #enddate))
First of all, do not convert your start/end and column's dates to varchar, and if you do so remember that 105 (returns dd-mm-yyyy) is not comparable, 112 (returns yyyymmdd) would be better (when you are interested in date part only). But what I've said it's better not to convert and just compare dates.
Added:
And little explanation: dateadd(dd, 0, datediff(dd, 0, #startdate)) - returns date part only of datetime, dateadd(dd, 1, datediff(dd, 0, #startdate)) - returns next day date part only.
Query returns all rows for your parameters inclusively (regardless of the hour).

Since you're on SQL Server 2008 R2, you could just convert everything to the DATE format:
SELECT *
FROM dbo.INVOICES INV
WHERE CAST(INV.CREATED_DATE AS DATE)
BETWEEN CAST(#startdate AS DATE) AND CAST(#enddate AS DATE)
Since you're using the DATE type, you're independent of any dateformat or language settings or any of those tricky features. SQL Server will just compare dates - as it should.
And of course: if you make your stored procedure parameters #startdate and #enddate to be of type DATE from the beginning, then you can save yourself those two CAST operations, too!
SELECT *
FROM dbo.INVOICES INV
WHERE CAST(INV.CREATED_DATE AS DATE) BETWEEN #startdate AND #enddate
(and if you made CREATED_DATE of type DATE - you could even forget about that last CAST in the statement, too!)

Default setting is yyyy-MM-dd
If you use 105 which means you're trying to parse date as format dmy, so before executing add below line at the top of your query.
SET DATEFORMAT DMY

Related

SQL - Correct dates not being presented in result set with date ranges in WHERE clause

Result set without the where clause shows there is data from the 30th September, when using the below where clause the 30th data doesn't come through in the result set (see images below for result sets) - my main aim is to show data from between the first day of the previous month and the last day of the previous month - Any help is much appreciated:
SQL Query
DECLARE #date1 datetime
DECLARE #date2 datetime
SET #date1 = getdate()
SET #date2 = getdate()-15 -- reason for less 15 days is because this will only be run within the first 15 days
-- of the current month, it will enable me to get the last day of the previous
-- month even if I run the SQL in the next month.
SELECT
A.TA_SEQ as 'WO No',
A.TA_DUE_DATEUTC
FROM
F_TASKS A WITH (NOLOCK)
INNER JOIN FINFILE B WITH (NOLOCK) ON A.TA_FKEY_IN_SEQ = B.IN_SEQ
INNER JOIN InstructionSetGroups C WITH (NOLOCK) ON B.InstructionSetGroupId = C.InstructionSetGroupId
WHERE
A.TA_TASK_DESC = 'BREAKDOWN' AND
A.TA_STATUS IN ('ACTIVE', 'ASSIGNED', 'COMPLETE', 'HISTORY') AND
A.TA_DUE_DATE >= DATEADD(DAY, 1, EOMONTH(#date1, -2)) AND
A.TA_DUE_DATE <= EOMONTH(#date2)
ORDER BY
A.TA_DUE_DATE desc
Result Sets
Result set using date ranges in where clause:
Result set without using date ranges in where clause - as you can see there's lots of data from the 30th too which isn't being captured
EOMONTH is terribly ambiguous, because it returns the last day of the month at midnight. I talk about why I don't like this function in Will you use EOMONTH()?
If you want the whole previous month, there are easier and safer ways than assuming the code will run within the first 15 days:
DECLARE #ThisMonth date = DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1);
SELECT ... FROM ...
WHERE TA_DUE_DATE >= DATEADD(MONTH, -1, #ThisMonth)
AND TA_DUE_DATE < #ThisMonth;
I explain why DATEFROMPARTS is best suited for this kind of work in Simplify Date Period Calculations in SQL Server.
With the rest, where do we begin?
getdate()-15 is lazy, unintuitive shorthand that will break in other contexts. Please use DATEADD(DAY, -15, GETDATE()) and see Bad Habits to Kick : Using shorthand with date/time operations.
You can declare/set in a more readable way than an explicit line for each declare and again for each set:
DECLARE #date1 datetime = GETDATE(),
#date2 datetime = DATEADD(DAY, -15, GETDATE());
as 'WO No' - please use AS [Wo No] or AS "Wo No" - string delimiters make those aliases look like, well, strings, and some forms of that syntax are deprecated.
please always specify the schema and never use meaningless aliases like A, B, C.
>= AND <= is the same as BETWEEN. I talk about why BETWEEN is always a terrible idea for date ranges in What do BETWEEN and the devil have in common?
Lots of resources on NOLOCK in I'm using NOLOCK; is that bad?
General date tips in Dating responsibly
I would take a different approach to handling your date values. That whole -15 stuff is bizarre and will cause issues on days towards the end of the month. Instead using a single variable is sufficient if you understand some date math.
DECLARE #date1 date --use the data datatype here because time is important in this case
SET #date1 = getdate()
--this is to show you the values and can be removed.
select BeginningOfLastMonth = dateadd(month, datediff(month, 0, #date1) - 1, 0)
, BeginningOfCurrentMonth = dateadd(month, datediff(month, 0, #date1), 0)
--Your select statement here
where A.TA_DUE_DATE >= dateadd(month, datediff(month, 0, #date1) - 1, 0)
A.TA_DUE_DATE <= dateadd(month, datediff(month, 0, #date1), 0) --ANY datetime value less than this is before the end of last month

How to get only date part while using dateadd() and getdate()

I want to display records of last 4 months from current date.
I don't want to consider time
How can I get just date part from the below query?
where OrderDate >= DATEADD(month, -4, GETDATE())
If you're using SQL Server 2008, try converting GETDATE() to a DATE directly.
WHERE OrderDate >= DATEADD(month, -4, CONVERT(date, GETDATE()))
http://sqlfiddle.com/#!3/df444/2
Why not use the simple DATEDIFF function
where DATEDIFF(MM, OrderDate, GETDATE()) < 4
If you can't use the DATE type, there's the old way: convert the DATETIME value to CHAR, trim the hour components and then convert it back to DATETIME, so the hour components will be zeroed:
SELECT CONVERT(DATETIME, CONVERT(CHAR(8), GETDATE(), 112), 112)
-- -----------------------
-- 2014-02-25 00:00:00.000
The important thing is to use the function over the scalar parameter (and not on the column) to allow the usage of existing indexes.

How to get 00:00:00 in datetime, for First of Month?

I wrote a query to obtain First of month,
SELECT DATEADD(DAY, -(DATEPART(DAY,GETDATE())-1), GETDATE()) as First_Of_Month;
for which i do get the appropriate output, but my time stamp shows the current time.
Here's what I am doing in the query, hope i make sense.
using datepart i calculated the no. of days (int) between the 1st and today (27-1 =26)
Then using dateadd function, i added "-datepart" to get the first of the month.
This is just changing the date, what should i look at or read about in order to change the time. I am assuming that it would have something to do with 19000101
For SQL Server 2012 (thanks adrift and i-one)
DECLARE #now DATETIME = CURRENT_TIMESTAMP;
SELECT DATEADD(DAY, 1, EOMONTH(#now, -1));
-- or
SELECT DATEFROMPARTS(YEAR(#now), MONTH(#now), 1);
For SQL Server 2008+
DECLARE #now DATETIME = CURRENT_TIMESTAMP;
-- This shorthand works:
SELECT CONVERT(DATE, #now+1-DAY(#now));
-- But I prefer to be more explicit, instead of relying on
-- shorthand date math (which doesn't work in all scenarios):
SELECT CONVERT(DATE, DATEADD(DAY, 1-DAY(#now), #now));
For SQL Server 2005
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0);
A caveat if you're using this SQL Server 2005 method: you need to be careful about using expressions involving DATEDIFF in queries. SQL Server can transpose the arguments and lead to horrible estimates - as seen here. It might actually be safer to take the slightly less efficient string approach:
SELECT CONVERT(DATETIME, CONVERT(CHAR(6), GETDATE(), 112) + '01');
SELECT convert(varchar(10),DATEADD(DAY, - (DATEPART(DAY,GETDATE())-1), GETDATE()),120)+' 00:00:00' as First_Of_Month;
Just the date
DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0)
So for a month it is:
DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0) AS FirstDatetimeOfMonthmm,
I think the easiest way is to cast the result to date:
SELECT cast(DATEADD(DAY, -(DATEPART(DAY,GETDATE())-1), GETDATE()) as date) as First_Of_Month
One alternative:
SELECT cast(
cast(datepart(yyyy, getdate()) as varchar)
+ '-'
+ cast(datepart(mm, getdate()) as varchar) + '-01 00:00:00'
as datetime)
Build up the date from year/month components, then tack on the 1st and midnight.
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) as First_Of_Month;
Try following code:
SELECT CAST(CAST(GETDATE() AS DATE) AS DATETIME) AS StartDateTime,
DATEADD(ms, -3, CAST(CONVERT(date, DATEADD (DAY,1,GETDATE())) AS varchar(10))) AS EndDateTime
Result:
StartDateTime
EndDateTime
2022-05-23 00:00:00.000
2022-05-23 23:59:59.997

Sql query for selecting entries with today's date

I have the following table in sql server 2008 (Called "act_events"):
As you notice some of the datetimes are formated: "yyyy-mm-dd" and some: "yyyy-dd-mm" for some weird reason I still haven't figured..
I have a query as follows:
SELECT * from act_events
WHERE '2013-07-30'>=(CAST(e_start as DATE)) AND
'2013-07-30'<=(CAST(e_end as DATE))
Where I want to select events only with today's date.
But I can't figure a way to select both formats..
I tries this query:
SELECT * from act_events
WHERE( #date1>=(CAST(e_start as DATE)) AND
#date2<=(CAST(e_end as DATE)) ) OR
( #date3>=(CAST(e_start as DATE)) AND
#date4<=(CAST(e_end as DATE)) )
But it only works for certain dates..
Would appreciate your answers.
Also, if there's a statement that will change all datetime to correct format I would love to hear.
Assuming the dates are indeed of type DateTime, what you could do in this case is to use dateadd and datediff.
Run these two statements:
-- Todays date, date part only
select dateadd(dd, 0, datediff(dd, 0, getdate()))
-- Tomorrows date, date part only
select dateadd(dd, 0, datediff(dd, 0, dateadd(dd, 1, getdate())))
Using those two, you can do this (Including edits, thanks #gvee)
select *
from act_events
where
e_start >= dateadd(dd, 0, datediff(dd, 0, getdate()))
and
e_end < dateadd(dd, 0, datediff(dd, 0, getdate()) + 1)
I should mention that getdate() is a built-in function in SQL Server. You could of course change this to a variable if you are using this in a stored procedure for example.
As a side note, the date in SQL Server is actually a number. The format that comes out when you look at it is for humans and humans are not to be trusted, right?
select *
from t
where
CONVERT(nvarchar(30), GETDATE(), 112)=substring(date_c,1,4)
+substring(date_c,6,2)
+substring(date_c,9,2)
or
CONVERT(nvarchar(30), GETDATE(), 112)=substring(date_c,1,4)
+substring(date_c,9,2)
+substring(date_c,6,2)
SQLFiddle demo

checking for smalldatetime column equal to GetDate() - ignoring time

I have a column of smalldatetime type, date
I'd like to run a query that only retrieves rows:
where date = convert(smalldatetime,GetDate())
However, this is never finding matches as it is also comparing the times.
Ie: 01-01-2010 12:23:00 != 01-01-2010 12:25:00
How can I find matches on only the date portion?
One way which will utilize the index
where date >= dateadd(dd, datediff(dd, 0, getdate()), 0)
and date < dateadd(dd, datediff(dd, 0, getdate()), +1)
See also: How Does Between Work With Dates In SQL Server?
Try:
where datediff(dd, yourdate, GetDate()) = 0
Convert your DateTime values to Date values. That will store only the date portion for you to compare.
A list of available Date and Time datatypes in MSSQL is here.
You could try:
Where CAST(FLOOR(CAST([Date] AS FLOAT)) AS DATETIME) = CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)
This would make both dates appear as:
2010-08-05 00:00:00.000
and thus only comparing the dates ignoring the times
found this:
CAST(CONVERT (CHAR(8), GETDATE(), 112) AS smalldatetime)
from here:
reference
this sql worked for me when I added a smalldatetime field to an existing table:
SELECT testing
FROM LTCCAssessment
WHERE (testing = CAST(CONVERT(CHAR(8), GETDATE(), 112) AS smalldatetime))
where cast(CONVERT(char(10),DATETIME_FIELD_1,101) as datetime)
= cast(CONVERT(char(10),DATETIME_FIELD_2,101) as datetime)