Issue with Fetching Date using SYSDATE? - sql

I have a table structure having a EMP_DATE column as below
ID EMP_DATE
---- -----------
5400 14-FEB-2012
and i have inserted records into the table as below
INSERT INTO TEST_DATE VALUES(5400,SYSDATE);
After inserting records while i am trying to fetch the records of those who has EMP_DATE
as SYSDATE its giving no rows selected.
For time being let the SYSDATE be '01-JUL-2012`
SELECT * FROM TEST_DATE WHERE EMP_DATE = SYSDATE;
(OR)
SELECT * FROM TESt_DATE WHERE EMP_DATE = '01-JUL-2012';
i was not able figure out any solution .
Any suggestions would be helpful .

The main problem is that a date includes hours, minutes and seconds, which you're not allowing for. If you want everything for a single day you can use the trunc function in order to get this:
SELECT * FROM TEST_DATE WHERE trunc(EMP_DATE) = trunc(SYSDATE);
By default trunc removes the time portion of a date, when operating on a date column. I would normally recommend a functional index on trunc(emp_date) in order to optimize this query. Something like:
create index i_test_date on test_date(trunc(emp_date));
I've built a little SQL Fiddle to demonstrate this.
There is an additional problem; though Oracle does support ANSI date literals your second query is wrong. Always, explicitly convert to a string to a date using the to_date function.
SELECT * FROM TEST_DATE WHERE EMP_DATE = to_date('01-07-2012','dd-mm-yyyy');
I've used the mm datetime format model instead of mon as there's no guarantee that JUL will always mean July; it depends on your NLS parameters, what "date language" your particular database or session is using. A datetime format model is how you tell the database the format of whatever string you're passing it to be converted into a date.
If you're interested the ANSI syntax for your second query would be:
SELECT * FROM TESt_DATE WHERE trunc(EMP_DATE) = DATE '2012-07-01'
It must be in this format (YYYY-MM-DD) to work.

Related

Oracle: efficiently where clause to filter timestamp column to get all records of a specific day

I have a monthly partitioned table in Oracle by a timestamp column. This table contains > 1 billion rows from a 2019 history data. Now I want to filter this table to get all results for a specific day, regarding the HH24:MI:SS part.
The Problem (#1) I'm facing is that when using TO_CHAR(TIMESTAMPCOLUMN, 'YYYY-MM-DD'), the running time of my queries increases for more recent months. Example:
SELECT * FROM BIG_PART_TABLE WHERE TO_CHAR(TIMESTAMPCOLUMN, 'YYYY-MM-DD') = '2019-01-01' -- 3 sec
SELECT * FROM BIG_PART_TABLE WHERE TO_CHAR(TIMESTAMPCOLUMN, 'YYYY-MM-DD') = '2019-02-01' -- 6 sec
SELECT * FROM BIG_PART_TABLE WHERE TO_CHAR(TIMESTAMPCOLUMN, 'YYYY-MM-DD') = '2019-12-01' -- 36 sec
So I got rid of the TO_CHAR and started to filter like this:
SELECT * FROM BIG_PART_TABLE WHERE TIMESTAMPCOLUMN BETWEEN DATE '2019-01-01' AND DATE '2019-01-02' -- 0.032 sec
SELECT * FROM BIG_PART_TABLE WHERE TIMESTAMPCOLUMN BETWEEN DATE '2019-12-01' AND DATE '2019-12-02' -- 0.031 sec
The Problem (#2) is that I'm to lazy to write a BETWEEN clause, apart from the fact that it increases the chance of errors.
Finally, what I really want is a efficient single where clause to filter my table, like:
SELECT * FROM BIG_PART_TABLE WHERE TIMESTAMPCOLUMN = DATE '2019-01-01'
Thanks for all.
The correct approach is not to use date functions on the date column - using functions like this makes the query non SARGable, meaning that it cannot take advantage of an index on the date column.
There is no syntactical sugar that would make the expression shorter to write.
I would also suggest using half-open intervals instead of between:
WHERE
TIMESTAMPCOLUMN >= DATE '2019-01-01'
AND TIMESTAMPCOLUMN < DATE '2019-01-02'
BETWEEN is inclusive on both ends, so your expression implies that timestamps on 2019-01-02 00:00:00 would be filtered in, while this is most likely not what you want.
Use the partition_extension_clause syntax:
SELECT *
FROM BIG_PART_TABLE PARTITION FOR (DATE '2019-12-01')
WHERE TRUNC(TIMESTAMPCOLUMN) = DATE '2019-12-01' ;
This code is still a bit messy. But at least this syntax allows you to use the same date literal instead of having to create a brand new date expression. And although the code has duplication, the duplication is a bit self-documenting: the first expression is to use partition-pruning to find the nearest segment, the second expression is to get the exact rows.
In order to use the partitioning, Oracle has to recognize the partitioning key. If it is using the full timestamp, then you might have a problem.
There is a reasonable chance it is using trunc(TIMESTAMPCOLUMN) or trunc(TIMESTAMPCOLUMN, 'DD'). If so, then you can use that
WHERE TRUNC(TIMESTAMPCOLUMN) = DATE '2019-01-01'
Once you figure it out, you can add a computed column to the table, so you have:
alter table big_part_table add column timestampcolumn_date as trunc(timestampcolumn);
Then you can use timestampcolumn_date in the WHERE clause.
In the fastest way to in Orace access data is to use the partition-name.
Like in this example:
select * from BIG_PART_TABLE partition(ParititonName);

Date difference = 0 in where clause Oracle?

I have the same problem as this. The only difference is that I use Oracle. I want to select the rows which has insertion_date='20.11.2018'. So my query was
select * from table where insertion_date='20.11.2018'
In that question they suggested datediff, so I looked at its equivalent in oracle and I learned that I can do date arithmetic. So I tried somethings like these:
select * from table where insertion_date -'20.11.2018'=0;
It gave ora-00932 inconsistent datatypes expected date got number.
So, then I tried;
select * from table where insertion_date - to_date('20.11.2018', 'dd.MM.YYYY') = 0;
It does not give error but also does not display the results which I know there must be. What am I doing wrong here? Thanks.
Update: Sorry I forgot to mention that insertion_date is type date. But it also has time(hour, minutes, seconds) info in it.
What is INSERTION_DATE's datatype?
If it is DATE, then comparing it to another date (note: this is date literal; value you used is a string!)
select * from table where insertion_date = date '2018-11-20'
might work, unless INSERTION_DATE contains time component (hours and minutes). Then, the simplest option is to truncate its value (so that you get date itself, at midnight):
select * from table where trunc(insertion_date) = date '2018-11-20'
but it'll ruin index you have on that column (unless it is a function-based one). For small tables, it won't make any difference. For large amount of data, it would so convert it to
select * from table where insertion_date >= date '2018-11-20'
and insertion_date < date '2018-11-21'
If, on the other hand, INSERTION_DATE is a string (VARCHAR2 or CHAR) datatype (which is a really bad idea; consider switching to DATE datatype), then you have to know its format, convert it to DATE first and then compare to another date. For example, if it was a string that contains date values in format dd.mm.yyyy, then
select * from table where to_date(insertion_date, 'dd.mm.yyyy') = date '2018-11-20'
This will certainly fail if any string in that column doesn't match such a format or contains invalid values (such as "date" 53.67.Bx48).

Issue querying date from oracle.

I understand that querying a date will fail as its comparing a string to date and that can cause an issue.
Oracle 11.2 G
Unicode DB
NLS_DATE_FORMAT DD-MON-RR
select * from table where Q_date='16-Mar-09';
It can be solved by
select * from table where trunc(Q_date) = TO_DATE('16-MAR-09', 'DD-MON-YY');
What I don't get is why this works.
select* from table where Q_date='07-JAN-08';
If anyone can please elaborate or correct my mindset.
Thanks
Oracle does allow date literals, but they depend on the installation (particularly the value of NLS_DATE_FORMAT as explained here). Hence, there is not a universal format for interpreting a single string as a date (unless you use the DATE keyword).
The default format is DD-MM-YY, which seems to be the format for your server. So, your statement:
where Q_date = '07-JAN-08'
is interpreted using this format.
I prefer to use the DATE keyword with the ISO standard YYYY-MM-DD format:
where Q_Date = DATE '2008-01-07'
If this gets no rows returned:
select * from table where Q_date='16-Mar-09';
but this does see data:
select * from table where trunc(Q_date) = TO_DATE('16-MAR-09', 'DD-MON-YY');
then you have rows which have a time other than midnight. At this point in the century DD-MON-RR and DD-MON-YY are equivalent, and both will see 09 as 2009, so the date part is right. But the first will only find rows where the time is midnight, while the second is stripping the time off via the trunc, meaning the dates on both sides are at midnight, and therefore equal.
And since this also finds data:
select* from table where Q_date='07-JAN-08';
... then you have rows at midnight on that date. You might also have rows with other times, so checking the count with the trunc version might be useful.
You can check the times you actually have with:
select to_char(q_date, 'YYYY-MM-DD HH24:MI:SS') from table;
If you do want to make sure you catch all times within the day you can use a range:
select * from table where
q_date >= date '2009-03-16'
and q_date < date '2009-03-17';
Quick SQL Fiddle demo.
Although it sounds like you're expecting all the times to be midnight, which might indicate a data problem.

Sort Date stored in SQLite database

I'm using a SQLite database (not mine) and I have to sort some data, order by date.
I have done many searches on the web but no solutions found!
The type of the field with the dates is "Date", with the format: DD/MM/YYYY HH:mm:SS
I tried many functions like strftime, datetime, date, ... But I can't sort the date correctly.
For example, if I do something like this:
SELECT * FROM events ORDER BY start_date
The date 04/10/2013 00:00:00 is after 03/12/2013... You know what I mean ?
I really don't know how I can sort in this format.
Thanks for your help
UPDATE 1:
I tried something like this:
SELECT start_date FROM events ORDER BY strftime('%d/%m/%Y %H:%M:%S', start_date)
Is this the right way to do ?
Results: No error, but nothing has changed. The dates are not sorted.
UPDATE 2:
Solution by laalto:
select * from tab order by substr(col,7,4)||'-'||substr(col,4,2)||'-'||substr(col,1,2)||'T'||substr(col,12);
The best way is to make the data sortable at insertion phase e.g. by inserting ISO-8601 stamps or unixtime integers, but since it's not your database, let's assume you can't influence that.
You can use substr() to extract parts from the datetime string and construct e.g. a ISO-8601 datetime string that you can sort lexicographically, resulting in chronological order.
Example:
sqlite> create table tab(col);
sqlite> insert into tab values('04/10/2013 00:00:00'),('03/12/2013 00:00:00');
sqlite> select substr(col,7,4)||'-'||substr(col,4,2)||'-'||substr(col,1,2)||'T'||substr(col,12) as date from tab order by date;
2013-10-04T00:00:00
2013-12-03T00:00:00
sqlite> select * from tab order by substr(col,7,4)||'-'||substr(col,4,2)||'-'||substr(col,1,2)||'T'||substr(col,12);
04/10/2013 00:00:00
03/12/2013 00:00:00

Between operation for date in SQLite database

I have a table student with the following columns:
no - integer
name - string
startdate - date
enddate - date.
Date format is MM/DD/YYYY.
I will give a date as input. Now I need a query the inputdate which found in between the start and end date.
For an example I will give 04/14/2012, then the query should return the 1st record as in the figure.
(because input date (04/14/2012) is found in between the 04/10/2012 to 04/20/2012)
Please help me.
The issue you are having is caused by your assumption that sqlite has a date/datetime type when in fact it doesn't.
I suggest you read the following http://www.sqlite.org/datatype3.html to have a better understanding of sqlite types.
The dates in the MM/DD/YYYY format are handled as TEXT by sqlite, and so those dates are compared as strings. For example, 02/01/2012 is considered bigger than 01/02/2012by sqlite if compared directly.
You will need to transform those dates to a format that can be string-compared. Here is an example:
sqlite> create table foo (d TEXT);
sqlite> insert into foo values ('02/01/2012');
sqlite> select substr(d, 7, 4) || substr(d, 1, 2) || substr(d, 4, 2) from foo;
20120201
You should post what you have tried so far.
There should be a between clause that you can use:
select * from table
where inputdate between startdate and enddate
Dates as a date type in SQLite don't exist. There are a number of approaches to dealing with dates - store them as integer seconds since 1 Jan 1970 (unixepoch) or store them as strings, but if you do, then you really need to store them in 'YYYY-MM-DD' format because that is what the date functions require as input.
Assuming you use the string format in the format I suggested then your query would look something like
SELECT * FROM Table WHERE Date(Inputdate) BETWEEEN Date(startDate) AND Date(EndDate);
(although you may want to format the output of the date columns to US date format with
SELECT Strftime("%m/%d/%Y",startDate) As StartDate ...
If you use seconds since 1970 its somewhat easier because the seconds just compare without needing the convert them to dates, although you still might want to output in US date format, so ...
SELECT Strftime("%m/%d/%Y",startDate) As StartDate ... FROM Table WHERE inputDate BETWEEN startDate and EndDate;
sqlite> select *from tbl_node where mydate between '2014-02-02' and '2014-02-06';
it show the output :-
1|1|123|456|12eb-ab|1|1|254|123|19|2014-02-03 16:00:44
2|1|123|456|12eb-ab|1|1|254|123|19|2014-02-03 16:01:03
3|1|123|456|12eb-ab|1|1|254|123|19|2014-02-03 16:00:57
4|1|123|456|12eb-ab|1|1|254|123|19|2014-02-03 16:00:34
Here mydate is column name in tbl_node;
we can also use from current time , using now.
sqlite> select *from tbl_node where mydate between '2014-02-02' and 'now';