I have a table which is having timestamp column as follows
ID timeStamp var1 var2 var3
1 05-09-2013 18:23:56 0 1 1
2 05-09-2013 18:23:57 0 0 1
3 05-09-2013 18:23:58 1 0 1
4 05-09-2013 18:23:59 1 0 1
I want to retrieve according to timestamp like timestamp>05-09-2013 18:23:56 and timestamp <05-09-2013 18:23:59
I am trying these ways
select * from test where timeStamp<'05-09-2013 18:23:59' and timeStamp>'05-09-2013 18:23:57'
Its giving null rows.I had tried using between keyword still not getting the desired result.
SELECT * FROM test
WHERE (timeStamp BETWEEN '05-09-2013 18:23:57' AND '05-09-2013 18:23:59')
May i know what wrong I am doing here?
here is the screen shot
This screenshot is without where clause
This screen shot shows table DESCRIPTION
Use appropriate datetime literals that don't break your queries. More and detailed explanations at Bad habits to kick : mis-handling date / range queries
SELECT *
FROM test
WHERE ( timeStamp BETWEEN '2013-09-05T18:23:57' AND '2013-09-05T18:23:59' ) ;
Also note that a timestamp with time part above 18:23:59.000, like '18:23:59.100' will not be included in the results because the above condition is equivalent to:
WHERE timeStamp >= '2013-09-05T18:23:57.000'
AND timeStamp <= '2013-09-05T18:23:59.000'
So, you may want this instead:
SELECT *
FROM test
WHERE timeStamp >= '2013-09-05T18:23:57.000'
AND timeStamp < '2013-09-05T18:24:00.000'
The use of BETWEEN in date and datetime comparisons is not advised, for this reasons. See another blog post by #Aaron Bertrand: What do BETWEEN and the devil have in common?
Related
How to retrieve specific month using date-time field let's say that i have following table
ID - DATETIME - AMOUNT
01 - 27/05/2017 - 1
02- 02/06/2017 - 2
03- 03/07/2017 - 1
04- 05/05/2017 - 2
05- 13/06/2017 - 3
What is the proper way to write a query to retrieve the records of May only
I have used the following query but it gave me error.
SELECT * FROM TABLE WHERE TABLE.DATETIME = '05/2017'
Msg 241, Level 16, State 1, Line 3
Conversion failed when converting date and/or time from character string.
You can use this (but if you have an index on the TABLE.DATETIME column, it will not be used):
SELECT *
FROM TABLE
WHERE MONTH(TABLE.DATETIME) = 5
AND YEAR(TABLE.DATETIME) = 2017
It may be more efficient (if you have or have plans to add an index) to do:
SELECT *
FROM TABLE
WHERE TABLE.DATETIME >= '20170501'
AND TABLE.DATETIME < '20170601'
Check against the start and end of month.
where DateTime >= '20170501' and
DateTime < '20170601'
Or you can use between clause:
SELECT *
FROM TABLE
WHERE TABLE.DATETIME BETWEEN '01/05/2017' AND '31/05/2017'
I have 2 SQL scripts. One like this:
"Date" > '2014-04-11' AND "Date" <= '2014-04-12'
the other one like this:
"Date" BETWEEN '2014-04-11' AND '2014-04-12'
Now i wonder if there is any specific best practice, one reason to do one over the other and if one of them is better for some apparent reason I missed somewhere down the road.
You are asking for best practices. I think the following is the best practice:
"Date" >= DATE '2014-04-11' AND "Date" < DATE '2014-04-12' + 1
First, note the use of the DATE keyword. You question is about dates and yet you are using a date format that Oracle does not directly support. Happily, Oracle support the ANSI standard DATE keyword with the ISO standard format.
Second, I added a +1 so you can see the end of the time period, which is presumably what you want to see in the code. It shouldn't affect performance because the + 1 is on a constant.
Third, a date constant has a time component. When none is specified, it is midnight on the date. So, the expression:
"Date" BETWEEN '2014-04-11' AND '2014-04-12'
Is really:
"Date" >= TIMESTAMP '2014-04-11 00:00:00' AND "Date" <= TIMESTAMP '2014-04-12 00:00:00'
That is, exactly one time from the later date is included, the first instant at midnight. This is not usually what you want. Oracle makes this problem worse in two ways:
The date data type includes a time component.
The default way of presenting date values has no time component.
So, to be safest, use the following rules:
Do not use between on dates.
Use >= for the first date.
User < for the second.
Aaron Bertrand has a blog on exactly this topic. Although it is specifically about SQL Server, many of the ideas apply to Oracle -- especially because the date data type in Oracle includes times.
SQL> create table date_tab as select sysdate + level d from dual connect by rownum < 10;
Table created.
Using between:
SQL> set autotrace traceonly
SQL> select * from date_tab where d between sysdate + 1 and sysdate + 3;
Execution Plan
----------------------------------------------------------
Plan hash value: 290508398
...
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(SYSDATE#!+1<=SYSDATE#!+3)
2 - filter("D">=SYSDATE#!+1 AND "D"<=SYSDATE#!+3)
Using date intervals:
SQL> select * from date_tab where d > sysdate + 1 and d <= sysdate + 3;
Execution Plan
----------------------------------------------------------
Plan hash value: 290508398
...
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(SYSDATE#!+1<SYSDATE#!+3)
2 - filter("D">SYSDATE#!+1 AND "D"<=SYSDATE#!+3)
As you can see, oracle optimizer rewrites the between predicate to "D">=SYSDATE#!+1 AND "D"<=SYSDATE#!+3 So if you use the second variant oracle performs less action than the first variant for one step.
I have a table for matches. The table has a column named matchdate, which is a datetime field.
If I have 3 matches on 2011-12-01:
2011-12-01 12:00:00
2011-12-01 13:25:00
2011-12-01 16:00:00
How do I query that? How do I query all matches on 1 single date?
I have looked at date_trunc(), to_char(), etc.
Isn't there some "select * where datetime in date" function?
Cast your timestamp value to date if you want simple syntax. Like this:
SELECT *
FROM tbl
WHERE timestamp_col::date = '2011-12-01'; -- date literal
However, with big tables this will be faster:
SELECT *
FROM tbl
WHERE timestamp_col >= '2011-12-01 0:0' -- timestamp literal
AND timestamp_col < '2011-12-02 0:0';
Reason: the second query does not have to transform every single value in the table and can utilize a simple index on the timestamp column. The expression is sargable.
Note excluded the upper bound (< instead of <=) for a correct selection.
You can make up for that by creating an index on an expression like this:
CREATE INDEX tbl_ts_date_idx ON tbl (cast(timestamp_col AS date));
Then the first version of the query will be as fast as it gets.
not sure if i am missing something obvious here, but i think you can just
select * from table where date_trunc('day', ts) = '2011-12-01';
Just use the SQL BETWEEN function like so:
SELECT * FROM table WHERE date BETWEEN '2011-12-01' AND '2011-12-02'
You may need to include times in the date literals, but this should include the lover limit and exclude the upper.
From rails I believe you can do:
.where(:between => '2011-12-01'..'2011-12-02')
I'm facing a strange query result and I want to ask you why I'm facing this issue.
I store some datetime data into TestTable as following :
creation_time
-----------------------
2010-07-10 00:01:43.000
2010-07-11 00:01:43.000
2010-07-12 00:01:43.000
This table is created and filled as following :
create table TestTable(creation_time datetime);
Insert into TestTable values('2010-07-10 00:01:43.000');
Insert into TestTable values('2010-07-11 00:01:43.000');
Insert into TestTable values('2010-07-12 00:01:43.000');
when I execute this query , I get two rows only instead of three as I expected:
SELECT * FROM TestTable
WHERE creation_time BETWEEN CONVERT(VARCHAR(10),'2010-07-10',111) -- remove time part
and CONVERT(VARCHAR(10),'2010-07-12',111) -- remove time part
Or if I execute this query , the same issue ..
SELECT * FROM TestTable
WHERE CONVERT(datetime,creation_time,111) BETWEEN CONVERT(VARCHAR(10),'2010-07-10',111) -- remove time part
and CONVERT(VARCHAR(10),'2010-07-12',111) -- remove time part
My Question :
Why the last row ('2010-07-12 00:01:43.000') does not appear in
the result even if I set the date range to cover all the day from 2010-07-10 to 2010-07-12?
I use Sql server 2005 express edition with windows xp 32-bits.
I'm trying to don't use a workaround solution such as increasing the date range to cover additional day to get the days I want.
Thanks .
You need to remove the time part from creation_time as well. Just use the same CONVERT if it works.
Currently you're asking if 2010-07-12 00:01:43.000 is less than 2010-07-12 00:00:00.000, which is not true.
it does not show the date because you have removed the time part, which would make the date equivalent to '2010-07-12 00:00:00.000' and since the last row is greater than this, so it is not displaying in the query results.
Your script should look like this:
SELECT *
FROM TestTable
WHERE creation_time BETWEEN
convert(datetime, convert(char, '2010-07-10', 106))-- remove time part
and **DATEADD**(day, 1, convert(datetime, convert(char, '2010-07-**11**', 106))) -- remove time part and add 1 day
This script will return all between 2010-07-10 00:00:00 and 2010-07-12 00:00:00. Basically this means all items created in 2 days: 2010-07-10 and 2010-07-11.
Converting columns in your table for comparison can be costly and cause indexes to not be used. If you have a million rows in your table and you have an index on creation_time, you will be doing an index scan and converting all million values to a string for comparison.
I find it better to use >= the start date and < (end date + 1 day):
SELECT *
FROM TestTable
WHERE creation_time >= '2010-07-10'
AND creation_time < dateadd(day, 1, '2010-07-12')
And the reason your second one may not work is because format 111 uses slashes ("2010/07/10"), format 120 uses dashes ("2010-07-10"). Your converts aren't doing anything to your start and end date because you are converting a string to varchar, not a date. If you did this, it might work, but I would still recommend not doing the conversion:
SELECT * FROM TestTable
WHERE CONVERT(datetime, creation_time, 111) BETWEEN
CONVERT(VARCHAR(10), CONVERT(datetime, '2010-07-10'), 111) -- remove time part
and CONVERT(VARCHAR(10), CONVERT(datetime, '2010-07-12'), 111) -- remove time part
Date/time inclusive between 7/10/2010 and 7/12/2010:
SELECT * FROM TestTable
WHERE creation_time BETWEEN
CONVERT(VARCHAR,'2010-07-10',101) -- remove time part
and CONVERT(VARCHAR,'2010-07-13',101) -- remove time part
We have a table which has a DATE column d.
I'd like to get all the rows where the d column is greater / lower than some value, regardless of the date.
For example
| d |
-------------------
|2009/11/1 15:55:23|
--------------------
|2009/11/2 15:55:23|
--------------------
|2009/11/3 15:55:23|
--------------------
|2009/11/3 17:55:23|
--------------------
For example, If I want all the records marked after 5 PM:
select d
from my_table
where extract( hour from d ) > TO_DATE ('17:00:00','HH24:MI:SS')
This should return only one record
|2009/11/3 17:55:23|
I don't know if this is the best way to do it, but I get an error on the extract function:
ORA-30076: invalid extract field for extract source
Cause: The extract source does not contain the specified extract field.
Is there a better way to do this?
Whats up with that error? extract only available for sysdate, as in all examples i've found?
Thanks in advance
How about this?
select d
from my_table
where to_char(d,'HH24') > '16';
Don't have an Oracle database to test with at the moment but I think the following should work:
SELECT *
FROM MY_TABLE t
WHERE EXTRACT(HOUR FROM CAST(t.D AS TIMESTAMP)) > 16;
But I don't understand why the CAST would be needed as this page says that HOUR is a valid field in a DATE.
Share and enjoy.
Try this:
select d from my_table
where (d-trunc(d)) > 16/24;