What happens when you do a comparison "date <= datetime" in SQL-server? - sql-server

What happens when you do a comparison "date <= datetime" in SQL-server?
Are they both cast to date or are they both cast to datetime in order to do the comparison?

datetime has higher precedence than date so the date will be cast to datetime.
This is documented here.
Or you can also see this below
DECLARE #D DATETIME = '2022-09-15 11:59:59';
SELECT CASE WHEN #D = CAST(#D AS DATE) THEN 'Equal' ELSE 'NotEqual' END
(Returns "NotEqual". If the implicit casting was to date and the time portion removed both would be equal)

Related

How to get date from yyyy-mm-dd to yyyy-mm-dd in SQL?

I want to get date from yyyy-mm-dd to yyyy-mm-dd in SQL.
Example: I have two parameter #startdate : 2015-12-28 and #enddate : 2016-01-02, and database in SQLServer, datatype is varchar(10)
DATE_ORDER
28-12-2015
30-12-1996
29-12-2016
30-12-1997
24-12-2015
27-12-1993
03-01-2016
01-01-1992
02-01-2016
etc...
Ok,now I want to get data from #startdate : 2015-12-28 and #enddate : 2016-01-02. I use SELECT * FROM TABLE_X WHERE DATE_ORDER >= #startdate AND DATE_ORDER <= #enddate . But the results are not what I expected. Here are the results I want
28-12-2015
30-12-1996
29-12-2016
30-12-1997
01-01-1992
02-01-2016
I think to solve this problem, I need to do two things :
First, get date range from #startdate to #enddate , in here 28/12/2015, 29/12/2015, 30/12/2015, 31/12/2015, 01/01/2016, 02/01/2016.
The second: get the date in database same in range 28/12, 29/12, 30/12, 31/12, 01/01, 02/01, ignoring the year.
Can you give me some ideas about this ?
Your actual format is "105-italian" find details here.
You can convert your existing VARCHAR(10)-values with this line to real datetime
SELECT CONVERT(DATETIME,YourColumn,105)
Next thing to know is, that you should not use BETWEEN but rather >=StartDate AND < NakedDateOfTheFollowingDay to check date ranges
So to solve your need Get date-range from 2015-12-28 to 2016-01-02 you might do something like this:
DECLARE #Start DATETIME={d'2015-12-28'};
DECLARE #End DATETIME={d'2016-01-02'};
SELECT *
FROM YourTable
WHERE CONVERT(DATETIME,YourDateColumn,105)>=#Start AND CONVERT(DATETIME,YourDateColumn,105)<#End+1
Attention Be aware, that the conversion lets your expression be not sargable. No index will be used.
Better was to store your date as correctly typed data to avoid conversions...
Try this query
SET DATEFIRST 1
DECLARE #wk int SET #wk = 2
DECLARE #yr int SET #yr = 2011
--define start and end limits
DECLARE #todate datetime, #fromdate datetime
SELECT #fromdate = dateadd (week, #wk, dateadd (YEAR, #yr-1900, 0)) - 4 -
datepart(dw, dateadd (week, #wk, dateadd (YEAR, #yr-1900, 0)) - 4) + 1
SELECT #todate = #fromdate + 6
;WITH DateSequence( Date ) AS
(
SELECT #fromdate AS Date
UNION ALL
SELECT dateadd(DAY, 1, Date)
FROM DateSequence
WHERE Date < #todate
)
--select result
SELECT * FROM DateSequence OPTION (MaxRecursion 1000)
So, after the 2nd or 3rd edit, it slowly becomes clear, what you want (i hope).
So you REALLY WANT to get the dates with the year beeing ignored.
As someone pointed out already, date-values are stored internally not as string, but as internal datatype date (whatever that is in memory, i don't know).
If you want to compare DATES, you cannot do that with ignorance of any part. If you want to, you have to build a NEW date value of day and month of given row and a hard coded year (2000 or 1 or whatever) for EVERY row.
SELECT * FROM TABLE_X WHERE convert(date,'2000' + substring(convert(char(8),convert(datetime, 'DATE_ORDER', 105),112),5,4),112) >= #startdate AND convert(date,'2000' + substring(convert(char(8),convert(datetime, 'DATE_ORDER', 105),112),5,4),112) <= #enddate
If your startdate and enddate go OVER sylvester, you have to do 2 queries, on from startdate to 1231, one from 0101 to enddate.

SQL Server convert number to date

How do I convert a numbers in the columns with values like 20160912 into date formats of the form 09/12/2016 and order them by the dates in the date format.
You can use cast and convert built-in functions. Depending on what type is 20160912 you can do following.
A) int
declare #d int=20160912
select convert(varchar(20),convert(date,convert(varchar,#d)),101)
--step by step
declare #dStr varchar(20)
set #dStr = convert(varchar,#d) --'20160912'
-- or = cast(#d as varchar)
declare #dDate date --or datetime
set #dDate = convert(date, #dStr) --2016-09-12 (this is external representation)
--show in MM/dd/yyyy format
select convert(varchar(20), #dDate, 101) --magic 101 for MM/dd/yyyy
--09/12/2016
B) varchar just omit innermost conversion

How to convert int year into valid date format in my stored procedure

My stored proc has the following select statement:
select Name,Holiday from tblNames where ID = #ID and DATENAME(YEAR, GETDATE()) = #Year
When executing the statement I have an error
"Error converting data type int to nvarchar."
How can I convert #Year parameter to a correct year?
The return type of the datename function is nvarchar, you want the datepart function that returns an integer value, so change to DATEPART(YEAR, GETDATE()) instead.
datename is what you would use to get the name of a month or weekday.
Or you could use the year(getdate()) function instead as Gordon L mentioned in a comment.
I'd recommend to switch back from fixing specific error message to the original question. You have a date in your table and need to filter it by range. So just provide to server the range bounds. This will also avoid any conversions of stored data. To avoid tail time issue you may append '23:59:59.997' to the upper bound of range or (my advice) provide next date and compare by < instead of <=
set #startdate = ...
set #enddate = dateadd(dd, 1, ...)
select *
from mytable
where t.date >= #startdate and t.date < #enddate
Complicated conversions can make it impossible to use appropriate index. If you can convert your arguments and provide prepared values to server - strive to do so.

How to solve the date comparison issue in SQL Server?

I am using the following way to compare two dates:
if CONVERT(varchar(20), #ScheduleDate, 101) >= CONVERT(varchar(20), #CurrentDateTime, 101)
This is working fine for the current year, but when the comes in yearly like one date is 12/31/2012 and 1/1/2013 then its not working.
Please help me how can I resolve this.
why do you comparing strings?
you can compare dates
if #ScheduleDate >= #CurrentDateTime
but if your date contains time, I usually do
if convert(nvarchar(8), #ScheduleDate, 112) >= convert(nvarchar(8), #CurrentDateTime, 112)
112 datetime format is YYYYMMDD so it's good for compare dates
You have to remember that string comparison is from left to right, so "1/...." is smaller than "12/...".
You need to use DATETIME comparisons, not string comparison.
Something like
DECLARE #ScheduleDate DATETIME = '1/1/2013',
#CurrentDateTime DATETIME = '12/31/2012'
IF (#ScheduleDate >= #CurrentDateTime)
BEGIN
SELECT #ScheduleDate, #CurrentDateTime
END
DECLARE #ScheduleDateString VARCHAR(20) = '1/1/2013',
#CurrentDateTimeString VARCHAR(20) = '12/31/2012'
IF (CONVERT(DATETIME,#ScheduleDateString,101)>=CONVERT(DATETIME,#CurrentDateTimeString,101))
BEGIN
SELECT CONVERT(DATETIME,#ScheduleDateString,101),CONVERT(DATETIME,#CurrentDateTimeString,101)
END
SQL Fiddle DEMO
Note that if the variables are already datetimes, you do not need to convert them.
Assuming that both variables are currently DateTime variables, can't you just compare them without converting to strings?
declare #ScheduleDate DATETIME, #CurrentDateTime DATETIME
SET #ScheduleDate = '1 Jan 2013'
SET #CurrentDateTime = GetDate()
IF (#ScheduleDate >= #CurrentDateTime)
BEGIN
SELECT 'Do Something'
END
ELSE
BEGIN
SELECT 'Do Something Else'
END
when you use CONVERT(nvarchar(8), #ScheduleDate, 112) function it's return string instead of date.
so,
Use "112" DateFormat in Sql Server it's return string in "YMD" format without any sepration.
compare that string in your query and get desire output.
Such as "if CONVERT(nvarchar(8), #ScheduleDate, 112) >= CONVERT(nvarchar(8), #CurrentDateTime, 112)"
I would not use CONVERT to compare formatted strings. It is slow (well, more like microseconds, but still)
I use a UDF for SQL prior to version 2008
CREATE FUNCTION [dbo].[DateOnly] (#Date DateTime)
RETURNS Datetime AS
BEGIN
Return cast (floor (cast (#Date as float)) as DateTime)
END
and for versions >=2008 this approach
select convert(#MyDateTime as DATE)
Of course, you can compare datetime values directly, but to know whether two datetime values are on the same date (ignoring the time component), the above versions have proven to be effectivy.
Date : From and To with following format
from_Date# = #dateformat("#form.from#", "mm/dd/yyyy")
to_Date# = #dateformat("#now()#" + 1, "mm/dd/yyyy")
In SQL Statement
WHERE a.DateCreated >= CAST ('#from_date#' AS DATE) and a.DateCreated <= CAST('#to_date#' AS DATE)
This is working fine without any cast of original date time column

How to retrieve record from SQl using Date as parameter

in my table am storing one column(smalldatetime).
i need to retreive records by giving just date- and search the column specified above.
Ex:
10/6/2010 4:01:00 PM - this is the actual value in Column.
And i just want to search records from table by givin today's date. ..???
ALTER PROCEDURE [dbo].[spDisplayAllOpenPrepaidSales]
#preStatus int,
#preCompanyId int,
#preCounterId int,
#preBillerId int,
#today smalldatetime
AS
BEGIN
print #today
select * from PrepaidSaleHeader
where preOpenStatus = #preStatus And preCompanyId = #preCompanyId And
preCounterId = #preCounterId And preEntryUserId = #preBillerId And preDate > #today
order by preDate
END
And pass parameter like;
spDisplayAllOpenPrepaidSales 0,2,4,2,'10/06/2010 00:00:00 AM'
Now this retreives record but gives me back - date in 24-hour Format.
The SQL DateDiff function is your friend - see SQL DataDiff Function
ALTER PROCEDURE [dbo].[spDisplayAllOpenPrepaidSales]
#preStatus int,
#preCompanyId int,
#preCounterId int,
#preBillerId int,
#today smalldatetime
AS
BEGIN
print #today
select * from PrepaidSaleHeader
where preOpenStatus = #preStatus And preCompanyId = #preCompanyId And
preCounterId = #preCounterId And preEntryUserId = #preBillerId
And DateDiff(d,preDate,#today) = 0 --to find all dates matching the parameter, regardless of the time
order by preDate
END
You should use an ISO 8601 conformant format for the date, e.g.
spDisplayAllOpenPrepaidSales 0,2,4,2,'2010-10-06 00:00:00'
Times should be in 24hr form, not AM/PM form, so my local time now would be '13:02:00'. If you want all records for today, because the date value includes time, anything past the absolute beginning of today (00:00:00) is actually bigger that today. I always use the algorithm where myDate >= today and myDate < tomorrow, which translates to:
where preDate >= '2010-10-06' and preDate < '2010-10-07'
To achieve generality with this, use the DATEADD() function:
where preDate >= #today and preDate < DATEADD(day, 1, #today)
I'm going to assume you mean you want to retrieve all records which match todays' date regardles of the time part? If so you can do something quite simply, but clumsy as this.
Get the Day of year for teh column, and the year for the column, and compare against eh day of year for the current date and the year for the current date (Or whatever date you are comparing against).
SELECT * FROM MyTable WHERE DATEPART(dy,MyColumn) = DATEPART(dy,GETDATE()) AND DATEPART(yy,MyColumn) = DATEPART(yy,GETDATE())
So your procedure would look like:
ALTER PROCEDURE [dbo].[spDisplayAllOpenPrepaidSales]
#preStatus int,
#preCompanyId int,
#preCounterId int,
#preBillerId int,
#today smalldatetime
AS
BEGIN
print #today
select * from PrepaidSaleHeader
where preOpenStatus = #preStatus And preCompanyId = #preCompanyId And
preCounterId = #preCounterId And preEntryUserId = #preBillerId And DATEPART(dy,preDate) = DATEPART(dy,#today)) AND DATEPART(yy,preDate) = DATEPART(yy,#today)
order by preDate
END

Resources