Access query with date BETWEEN breaks when using parameters - sql

I have an SQL query in access that will grab all records where a calculated date is in between two values. It works fine if I hardcode date literals such as:
SELECT *
FROM Table
WHERE DateAdd("d",-60,DateAdd("yyyy",65,[Table].[BirthDate])) Between #3/21/2021# And #3/27/2021#;
However I need to parametrize the the between dates so that they can be entered by a user like:
SELECT *
FROM Table
WHERE DateAdd("d",-60,DateAdd("yyyy",65,[Table].[BirthDate])) Between [StartDate] And [EndDate];
However when I run the latter query and enter the exact same dates as the former, hard-coded one, it starts pulling records outside the between range. I've attempted to enter the dates like 3/21/2021 as well as date literals like #3/21/2021# and neither work. The latter doesn't pull anything at all.
I also have a form with a handful of text boxes using the short date format that let the user pick the dates for the query. It has the same issue of pulling back incorrect records. None of the records have any time component to my knowledge.
How can I get the date between to correctly work with user entered parameters?

Access doesn't know what data type your parameters are, so specify that in the query:
PARAMETERS
StartDate DateTime,
EndDate DateTime;
SELECT
*
FROM
Table
WHERE
DateAdd("d",-60,DateAdd("yyyy",65,[Table].[BirthDate])) Between [StartDate] And [EndDate];

Parameters worked to filter a native field - not the calculated date. However, using CDate() function worked.
SELECT *
FROM Table
WHERE DateAdd("d",-60,DateAdd("yyyy",65,[Table].[BirthDate]))
Between CDate([StartDate]) And CDate([EndDate]);
But before I remembered that, I tested calculating with inputs back to a birthdate range which also worked.
SELECT *
FROM Table
WHERE [BirthDate] Between DateAdd("d",60,DateAdd("yyyy",-65,[StartDate]))
And DateAdd("d",60,DateAdd("yyyy",-65,[EndDate]));

Related

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?

Comparing dates in SQL returns wrong records

I am trying to locate a date in database between two specific dates entered by user. Something like:
SELECT date FROM table WHERE date>=dateFrom AND date<=dateTO
I have the following table:
I have made a mistake saving the date as VARCHAR and now i have to do all the str_to_date and date_format as i am using phpMyAdmin. I somehow did it but i am facing this strange problem using this query:
SELECT date_format(str_to_date(data,'%d/%m/%Y'),'%d/%m/%Y') AS data FROM montaggio WHERE data>=date_format(str_to_date('29/08/2014','%d/%m/%Y'),'%d/%m/%Y')
The query would return to me only the date 19/08/2014 where as i expected it to return 01/09/2014. On the other hand if it enter the query
SELECT date_format(str_to_date(data,'%d/%m/%Y'),'%d/%m/%Y') AS data FROM montaggio WHERE data>=date_format(str_to_date('29/08/2014','%d/%m/%Y'),'%d/%m/%Y') AND data<=date_format(str_to_date('05/09/2014','%d/%m/%Y'),'%d/%m/%Y')
The query returns nothing.
I am using phpMyAdmin.
What am i missing here? Any help would be appreciated!
You do seem a bit confused. All the operations on dates should be done on the date data type. There is no need to convert things back to strings:
SELECT data
FROM montaggio
WHERE str_to_date(data, '%d/%m/%Y') >= str_to_date('29/08/2014', '%d/%m/%Y')
You seem to understand the real solution, which is to store dates/times in the database using the correct type. If you have to use strings for dates, then always stored them as YYYY-MM-DD, so comparisons and sorting will work correctly.

MsSQL - Return results within a date range

I was wondering if someone could help me out.
I need to return database results based on a date range, im using Classic ASP and MsSQL
My script gives me dates formatted as follows:
6/18/2014
The dates are saved in the database in the following format
12/24/2014 7:03:00 AM
What im wanting to do is something as follows:
SELECT * FROM table WHERE paid >= 6/18/2014 AND =< 6/28/2014
When i run that, im getting weird results as the dates arent formatted the same.
Can someone help me out.
Cheers,
you should put those two dates between single quotes like..
SELECT * FROM table WHERE paid BETWEEN '6/18/2014' and '6/28/2014'
EDIT:
you can use DATE_FORMAT(date,format) function to display date/time data in different formats.
here's some reference
http://www.w3schools.com/sql/func_date_format.asp
if its not typo
SELECT * FROM table WHERE paid BETWEEN '6/18/2014' AND '6/28/2014'
EDIT:-my database is storing it in the format yyyy-mm-dd
SELECT *
FROM table
WHERE DATE >= '2014-05-18'
AND DATE <= '2014-06-28'
and its working correctly
here is a reference
change the format according to your own database it will work

Does constructor DateTime take string or ONLY TIMESTAMP type as parameter?

I am working with SQLite SQL statement or Query.
So far, I was able to figure out some of things by asking stackoverflow question that can cause problem when executing such SQL Statement.
However, I still am not able to get any result?
Here is my SQL Query:
SELECT *
FROM Alarms
WHERE ALARMSTATE IN (0,1,2)
AND ALARMPRIORITY IN (0,1,2,3,4)
AND ALARMGROUP IN (0,1,2,3,4,5,6,7)
AND DateTime(ALARMTIME) BETWEEN datetime("2012-08-02 00:00:00")
AND datetime("2012-08-03 00:00:00")
ORDER BY ALARMTIME DESC
Here is my table as viewed within datagridView control:
As you can see, I have records from yesterdays and the day before in the table.
I corrected all the columns in question of their format such as my ALARMTIME, which is TEXT in data type. Still not getting any result, I decided to run the SQL statement right from within SQLite Administrator application as below. Surprisingly, I got the same result which is nothing or nill or null for dataset. However, SQLite Administrator showed me that DateTime accepts only TIMESTAMP as a parameter not TEXT. If so, my above SQL Statement won't work even if I have everything else correct. Am I correct in saying that?
Here is my answer. From what I understand, DATETIME supposed to take string or timestamp as a parameter, but in my case it doesn't work for me.
Since my column ALARMTIME is TEXT, I am able to query my table with the following SQL statement and retrieve dataset I am looking for.
SELECT *
FROM Alarms
WHERE ALARMSTATE IN (0,1,2)
AND ALARMPRIORITY IN (0,1,2,3,4)
AND ALARMGROUP IN (0,1,2,3,4,5,6,7)
AND ALARMTIME LIKE "2012/08/01%"
ORDER BY ALARMTIME DESC
I simply can't convert my ALARMTIME text into datetime type.
try using between 8/1 and 8/3 and you will get the ones for 8/2.
the way you have it should pull up the alarms in between the two times though
EDIT
can you change your ALARMTIME to a DATETIME format? Then you would be able to use the Between and you wouldn't have to convert the text to DATETIME.
if you Convert to DATETIME type you will have better flexibility in your query. it will be easier to use in the future as well.
I believe that DATETIME is a overloaded text type, so it should output text

How to update dates stored as varying character formats (PL/SQL)?

Problem: I have a large database table (~500k records) which has a list of dates stored in a varchar2(15) column. These dates are stored in varying formats, ie. some are yyyy-mm-dd, some are mm/dd/yyyy, some are dd/mm/yy, some are mm/dd/yy, etc. Ie:
1994-01-13
01/13/1994
01/13/94
13/01/94
13/01/1994
etc
I need to be able to shift these dates slightly, for example to add 30 days to each date. (This is an oversimplification of my objective but it's easier to explain this way).
If all the dates were formatted consistently, I would achieve this as follows:
UPDATE history_table
SET some_date_col =
to_char(to_date(some_date_col, 'mm/dd/yyyy')+30, 'mm/dd/yyyy')
WHERE some_date_col IS NOT NULL;
Due to the size of the database, I cannot afford to loop through the values one by one and parse the date value. Can anyone suggest a means to accomplish this without loops, ie with a mass UPDATE statement?
Are the formats of these dates really that important? They should be datetime columns. Then you could just use date math functions on that field.
well, you've got a real problem here.
07/07/1994 is valid for 'MM/DD/YYYY' and 'DD/MM/YYYY'
However, outside of that issue, you can try nesting decodes.
I entered the following dates into a varchar field:
01/12/2009, 01-12-2009, 2009-01-12, 01/12/09
and using the below, I was consistently returned 1/12/2009. You'll have to figure out all the patterns possible and keep nesting decodes. The other thing you could do is create a function to handle this. Within the function, you can check with a little more detail as to the format of the date. It will also be easier to read. You can use the function in your update statement so that should be faster than looping through, as you mentioned.
(for what its worth, looping through 500k rows like this shouldn't take very long. I regularly have to update row by row tables of 12 million records)
select mydate,
decode(instr(mydate,'-'),5,to_date(mydate,'YYYY-MM-DD'),3,to_date(mydate,'MM-DD-YYYY'),
decode (length(mydate),8,to_date(mydate,'MM/DD/YY'),10,to_date(mydate,'MM/DD/YYYY')))
from mydates;
and here is the update statement:
update mydates set revdate = decode(instr(mydate,'-'),5,to_date(mydate,'YYYY-MM-DD'),3,to_date(mydate,'MM-DD-YYYY'),
decode (length(mydate),8,to_date(mydate,'MM/DD/YY'),10,to_date(mydate,'MM/DD/YYYY')))
IMHO, you have a bigger problem:
If some dates are dd/mm/yyyy and some are mm/dd/yyyy how can you difference which format applies for certain date?
for example, how can I know if a value "12/09/2008" means December or September?