I have a Sql server table which contains below Date values(4th october)
Now Below query is not showing any result
select
*
from [dbo].[TB_AUDIT] TBA
where TBA.ActionDate >= '10/01/2018' and TBA.ActionDate <= '10/04/2018' which is not correct.
But If I write
select
*
from [dbo].[TB_AUDIT] TBA
where TBA.ActionDate >= '10/01/2018' and TBA.ActionDate <= '10/05/2018' it is returning me all results.
What I am doing wrong.
There are two problems with this query. The first, is that it's using a localized string. To me, it looks like it's asking for rows between January and April. The unambiguous date format is YYYYMMDD. YYYY-MM-DD by itself may not work in SQL server as it's still affected by the language. The ODBC date literal, {d'YYYY-MM-DD'} also works unambiguously.
Second, the date parameters have no time which defaults to 00:00. The stored dates though have a time element which means they are outside the search range, even if the date parameter was recognized.
The query should change to :
select
*
from [dbo].[TB_AUDIT] TBA
where
cast(TBA.ActionDate as date) between '20181001' and '20181004'
or
cast(TBA.ActionDate as date) between {d'2018-10-01'} and {d'2018-10-04'}
Normally, applying a function to a field prevents the server from using any indexes. SQL Server is smart enough though to convert this to a query that covers the entire date, essentially similar to
where
TBA.ActionDate >='2018:10:01T00:00' and TBA.ActionDate <'2018-10-05T00:00:00'
When you don't specify a time component for a DATETIME, SQL Server defaults it to midnight. So in your first query, you're asking for all results <='2018-10-04T00:00:00.000'. All of the data points in your table are greater than '2018-10-04T00:00:00.000', so nothing is returned.
You want
TBA.ActionDate >= '2018-10-01T00:00:00.000' and TBA.ActionDate < '2018-10-05T00:00:00.000'`
Use properly formatted dates!
select *
from [dbo].[TB_AUDIT] TBA
where TBA.ActionDate >= '2018-10-01' and TBA.ActionDate <= '2018-10-04'
YYYY-MM-DD isn't just a good idea. It is the ISO standard for date formats, recognized by most databases.
when you just filter by the date, it is with regard to the time as per the standard.
Related
I have a column with a DateTime type i want to query the table based on a condition that this data is in a certain year.
I tried this but didnt work
WHERE YEAR(InvoiceDate) = 2013; but didnt work
In general, you don't want to use functions on columns. This impedes the optimizer. This is better written as:
where invoicedate >= date '2013-01-01' and
invoicedate < date '2014-01-01'
Note: date is a SQL standard construct for a date literal. Some databases do not use this. Most databases support YYYY-MM-DD as a date literal.
Use year(invoice date ) = year (date('01-01-2013')) so that the data type on both the sides are same and the equality operator would be able to compare .
Some database though allow the query to compare the way you have written Db2 is one such db
I've written a query to check whether more than one record exists on the same day. Currently the excerpt from my query that performs the restriction looks like this :
GROUP BY
entry_date
HAVING
COUNT(entry_date) > 1
As the entry date column is defined as a datetime, does it check against the full datetime or just the date?
Thanks.
if entry_date is DATETIME ,your group by wont work as expected.you need to CAST it to DATE.Cast(Datetime)to date is sargable as well.
GROUP BY cast(entry_date as DATE)
having count(cast(entry_date as DATE)) > 1
Since you don't cast or convert it to anything else, naturally it uses all data available. So it would group data together with the exact same datetime. Why would you expect anything else?
It should be full datetime.
CONVERT(date, entry_date)
should separate out the date.
There is this strange error in sql query.
The query is something like this.
select * from student where dob between '20150820' and '20150828'
But in the database the column of dob is varchar(14) and is in yyyyMMddhhmmss format,Say my data in the row is (20150827142545).If i fire the above query it should not retrive any rows as i have mentioned yyyyMMdd format in the query.But it retrives the row with yesterday date (i.e 20150827112535) and it cannot get the records with today's date (i.e 20150828144532)
Why is this happening??
Thanks for the help in advance
You can try like this:
select * from student
where convert(date,LEFT(dob,8)) between
convert(date'20150820') and convert(date,'20150828'))
Also as others have commented you need to store your date as Date instead of varchar to avoid such problems in future.
As already mentioned you would need to use the correct date type to have between behave properly.
select *
from student
where convert(date,LEFT(dob,8)) between '20150820' and '20150828'
Sidenote: You don't have to explicitly convert your two dates from text as this will be done implicitly as long as you use an unambiguous date representation, i.e. the ISO standard 'YYYYMMDD' or 'YYYY-MM-DD'. Of course if you're holding the values in variables then use date | datetime datatype
declare #startdate date
declare #enddate date
select *
from student
where convert(date,LEFT(dob,8)) between #startdate and #enddate
Sidenote 2: Performing the functions on your table dob column would prevent any indexes on that column from being used to their full potential in your execution plan and may result in slower execution, if you can, define the correct data type for the table dob column or use a persistent computed column or materialised view if your performance is a real issue.
Sidenote 3: If you need to maintain the time portion in your data i.e. date and time of birth, use the following to ensure all records are captured;
select *
from student
where
convert(date,LEFT(dob,8)) >= '20150820'
and convert(date,LEFT(dob,8)) < dateadd(d,1,'20150828')
All you have to do is to convert first the string to date.
select *
from student
where dob between convert(date, '20150820') and convert(date, '20150828')
Why is this happening?
The comparison is executed from left to right and the order of characters is determined by the codepage in use.
Sort Order
Sort order specifies the way that data values are sorted, affecting
the results of data comparison. The sorting of data is accomplished
through collations, and it can be optimized using indexes.
https://msdn.microsoft.com/en-us/library/ms143726.aspx
There are problems with between in T-SQL.
But if you want a fast answer convert to date first and use >= <= or even datediff to compare - maybe write a between function yourself if you want the easy use like between and no care about begin and start times ...
What do BETWEEN and the devil have in common?
I have a very simple SQL which select data from a range of date. So, for example if I have,
SELECT ...... WHERE PV.[Time] BETWEEN '02/26/2014' AND '02/26/2014'
This SQL Select statement is not selecting the data in 02/26/2014. Please help
Your current statement BETWEEN '02/26/2014' AND '02/26/2014' has the same value on the left and right and so is equivalent to = '02/26/2014'.
This will only bring back rows at midnight on 26 Feb. Use
WHERE PV.[Time] >= '20140226' AND PV.[Time] < '20140227'
It's always preferable to use a non-dubious string format for dates (1/2/2000 can be interpreted as 01-feb-2000 or 02-jan-2000, depending on your local settings). I prefer the ISO format yyyymmdd or ODBC canonical yyyy-mm-dd and always use CONVERT to be explicit when handling dates. But this is not your problem :)
The problem with your query is that you are actually filtering dates BETWEEN '02/26/2014 00:00:00' AND '02/26/2014 00:00:00', thus you'll only get values at exactly the datetime. To get datetime values through whole day 02/26/2014 use the following:
SELECT ...
WHERE PV.[Time] >= '2014-02-26' AND PV.[Time] < dateadd(day, 1, '2014-02-26');
I'm using a datediff in SQL. It returns records when run directly in sql server 2008, but when I try and run it through ODBC it doesn't bring up an error, but it returns no rows.
SELECT mc_id, mc_date_entered,
COUNT([mv_value]) total
FROM MarkbookValue t1
RIGHT JOIN MarkbookColumn t2 ON t1.mv_column_id = t2.mc_id
WHERE mc_module_id = '703000026609358'
AND DateDiff(dd, mc_date_entered, '2012-10-05 20:00:00') = 0
AND mc_type = 'KEF'
AND mc_entered_by = 'A.ADMIN'
GROUP BY
mc_id, mc_date_entered;
Getting rid of the DateDiff lets the function run correctly, but I'd obviously like to have it in there. What am I doing wrong?
YYYY-MM-DD HH:MM:SS is not a safe date format to use for a date time literal value in SQL Server. Depending on SET DATEFORMAT your month and day part might be switched.
YYYY-MM-DDTHH:MM:SS and YYYYMMDD HH:MM:SS are safe to use regardless of SET DATEFORMAT.
To get the rows for a specific date I suggest that you do as in the answer provided by #RichardTheKiwi or if you are in SQL Server 2008 you can cast your column to date to remove the time part.
where cast(mc_date_entered as date) = '2012-10-05'
YYYY-MM-DD is safe for data type date.
I would almost always write dates in ISO-8601 format, the one without dashes being YYYYMMDD.
Just would like to also point out that if you want your query to use an index on mc_date_entered and remain SARGABLE, you'll want to rewrite it like this.
SELECT mc_id, mc_date_entered, COUNT([mv_value]) total
FROM MarkbookValue t1
RIGHT JOIN MarkbookColumn t2 ON t1.mv_column_id = t2.mc_id
WHERE mc_module_id = '703000026609358'
AND mc_date_entered >= '20121005'
AND mc_date_entered < '20121006'
AND mc_type = 'KEF'
AND mc_entered_by = 'A.ADMIN'
GROUP BY
mc_id, mc_date_entered;
Are you also aware that DATEDIFF(DD only considers the date portion, so there's really no point including the time (if we were still using DATEDIFF)?