SQL Server 2008 query check date on same day - sql

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.

Related

Sql Server Table date query showing incorrect result

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.

Strange behaviour of Sql query with between operator

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?

Find rows in SQL that with date when it is stored as datetime?

My problem is this (using SQL Server 2008 R2).
There is some date columns with types as datetime.
So the original intention with the column was to store a date without any time.
Then datetime was chosen as datatype.
Sure it works but as the database is also logically connected to a UML-diagram I want to use the right datatype.
An example the column Parcel.DateofArrival has the type datetime.
There maybe rows that are
2011-08-05 00:00:00.000
this is a date. But if there is rows like
2011-08-05 07:30:00.000
it is a datetime.
Now I want to find a query that list rows only containing dates, not datetime.
Any hint ?
An easy way to do this is:
select p.*
from Parcel p
where DateOfArrival = cast(DateOfArrival as Date);
By casting the value to a date, the datetime portion is lost. If the original value equals this, then there is no time component.
A way to do this would be to convert it in your select statement, for example:
SELECT CONVERT(DATE, DateOfArrival) Date, *other columns*
FROM Parcel P
Another solution, would be converting it to VARCHAR, formatting it in a yyyyMMdd format, like:
SELECT CONVERT(VARCHAR(8), DateOfArrival, 112) Date, *other columns*
FROM Parcel P
And if you want to sort it or group it, you have to use the conversion.
I hope it was helpful!
select p.*
from Parcel p
where cast(DateOfArrival as time) = '00:00'

SQL - comparing date parameter to datetime

In a SQL Server table, I have a field named Timestamp, which is a 'datetime' field. On a screen I have created, a user will pass in a date (no time), and I need to return all the records for that date.
Just doing Timestamp = #Date doesn't seem to work unless the time in the field is 00:00:00. What is the most efficient way of doing this?
Since you're on SQL Server 2008, you can use the DATE datatype.
Do a comparison between
CAST(Timestamp AS DATE) = #Date
That should work and look just at the date - no time portion.
In general you should think about the data from a specific date as data that falls in a range, not at a single point in time. So ideally your query should use a range, such as:
WHERE [Timestamp] >= #Date
AND [Timestamp] < DATEADD(DAY, 1, #Date)
In this case, luckily, the optimizer is smart and will still use an index if you use CONVERT(DATE, [timestamp]) against the column. However in a lot of cases you need to be careful because this will often make your clause non-sargable.
PS Timestamp is a horrible column name. It's a data type in SQL Server which has nothing to do with date or time.
A common technique for truncating the time part off a datetime value is to use the DATEDIFF and DATEADD functions. In your example it would be used like this to truncate the time part of the Timestamp field.
WHERE #DateEntered = DATEADD(DAY,0, DATEDIFF(DAY, 0, Timestamp))
Bascially it's taking the datetime value and finding the name of days since "the date represented by 0" (for lack of a better description) and then adding that number of days back. This effectively truncates time part.

Is this sql where statement correct?

I have 10 rows for today's date but my select statement based on date dosen't seem to work....
SELECT Id,WirelessId,RegNo,DriverName1,MobileNo1,DriverName2,MobileNo1 from
DailySchedule where IsDeleted=0 and CreatedDate='2010-05-28'
Any suggestion...
Only if the dates assigned to them are midnight today. It might be better to do:
CreatedDate BETWEEN '2010-05-28 00:00' AND '2010-05-29 00:00'
If you want all the entries for May 28th I would do
and CreatedDate >='20100528'
and CreatedDate < '20100529'
Notice the safe ISO format (YYYYMMDD) no dashes
Also take a look at How Does Between Work With Dates In SQL Server? to see why between can not give you all the results you want
Assuming that CreatedDate is a datetime or a date, I don't see what's wrong with the syntax of the where clause. Maybe the IsDeleted field for those columns is actually NULL? (Or non-zero, at any rate.)
Edit: what Dave says, or DATE(CreatedDate) = '2010-05-28'
I'd check to see the type of the CreatedDate column and make sure that the string you're passing is being converted to a date properly.
When you say you 'have' 10 rows, is that confirmed visually or with a query executed in a console?
Not enough info to go on but I suspect that your dates have a time component and so don't match the string exactly.
Try using:
datediff(day, CreatedDate, '28-may-2010')) = 0
SELECT Id,WirelessId,RegNo,DriverName1,MobileNo1,DriverName2,MobileNo1 from
DailySchedule where IsDeleted=0 and date_format(CreatedDate, "%Y-%m-%d")='2010-05-28'
This should work too
select Id,
WirelessId,
RegNo,
DriverName1,
MobileNo1,
DriverName2,
MobileNo1
from DailySchedule
where IsDeleted=0
and CONVERT(varchar,CreatedDate,101) ='05/28/2010'