What is the difference between these 2 sql queries? - sql

select * from accounts where sysdate - 100 < last_active_dt;
select * from accounts where sysdate - 100 <= last_active_dt;
Both of the queries returned the same result.
I was thinking that for the first query, it would not select
records on the day of last_active_dt. For the 2nd query, it
will select records on the day of last_active_dt.
But this does not seem to be the case as both returned the same results.
Is there any difference to it? And how can I see the difference?
last_active_dt column follows a date format DD-MON-YYYY

last_active_dt column follows a date format DD-MON-YYYY
No, it doesn't (but it may look like it does in the user interface you are using).
A DATE data type always has year, month, day, hour, minute and second components and is stored (without any formatting) in 7 bytes. It is the user interface that applies a (default) format to the date and this may hide the time component from you.
You can use:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
To change the default date format used in SQL*Plus (and SQL Developer) to see the date with all the components.
Equally, SYSDATE is of a DATE data type and has year, month, day, hour, minute and second components so what you are probably intending is:
select * from accounts where TRUNC( sysdate ) - INTERVAL '100' DAY < last_active_dt;
This will get all the columns where the last_active_dt is after midnight of the day 100 days ago (even if it 1 second after). This will work if all your last_active_dt values have the times TRUNCated to exactly midnight 00:00:00 but not if the column as non-zero time components as you will still get values with times from 00:00:01 to 23:59:59 of the day 100 days ago.
If your last_active_dt has a non-zero time component then you want:
select * from accounts where TRUNC( sysdate ) - INTERVAL '99' DAY <= last_active_dt;

Related

Date Functions Trunc (SysDate)

I am running the below query to get data recorded in the past 24 hours. I need the same data recorded starting midnight (DATE > 12:00 AM) and also data recorded starting beginning of the month. Not sure if using between will work or if there is better option. Any suggestions.
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CNLD'
AND
TRUNC(TO_DATE('1970-01-01','YYYY-MM-DD') + OPEN_DATE/86400) = trunc(sysdate)
Output (Just need Count). OPEN_DATE Data Type is NUMBER. the output below displays count in last 24 hours. I need the count beginning midnight and another count starting beginning of the month.
The query you've shown will get the count of rows where OPEN_DATE is an 'epoch date' number representing time after midnight this morning*. The condition:
TRUNC(TO_DATE('1970-01-01','YYYY-MM-DD') + OPEN_DATE/86400) = trunc(sysdate)
requires every OPEN_DATE value in your table (or at least all those for CNLD rows) to be converted from a number to an actual date, which is going to be doing a lot more work than necessary, and would stop a standard index against that column being used. It could be rewritten as:
OPEN_DATE >= (trunc(sysdate) - date '1970-01-01') * 86400
which converts midnight this morning to its epoch equivalent, once, and compares all the numbers against that value; using an index if there is one and the optimiser thinks it's appropriate.
To get everything since the start of the month you could just change the default behaviour of trunc(), which is to truncate to the 'DD' element, to truncate to the start of the month instead:
OPEN_DATE >= (trunc(sysdate, 'MM') - date '1970-01-01') * 86400
And the the last 24 hours, subtract a day from the current time instead of truncating it:
OPEN_DATE >= ((sysdate - 1) - date '1970-01-01') * 86400
db<>fiddle with some made-up data to get 72 back for today, more for the last 24 hours, and more still for the whole month.
Based on your current query I'm assuming there won't be any future-dated values, so you don't need to worry about an upper bound for any of these.
*Ignoring leap seconds...
It sounds like you have a column that is of data type TIMESTAMP and you only want to select rows where that TIMESTAMP indicates that it is today's date? And as a related problem, you want to find those that are the current month, based on some system values like CURRENT TIMESTAMP and CURRENT DATE? If so, let's call your column TRANSACTION_TIMESTAMP instead of (reserved word) DATE. Your first query could be:
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CLND'
AND
DATE(TRANSACTION_TIMESTAMP)=CURRENT DATE
The second example of finding all for the current month up to today's date could be:
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CLND'
AND
YEAR(DATE(TRANSACTION_TIMESTAMP)=YEAR(CURRENT DATE) AND
MONTH(DATE(TRANSACTION_TIMESTAMP)=MONTH(CURRENT DATE) AND
DAY(DATE(TRANSACTION_TIMESTAMP)<=DAY(CURRENT DATE)

Sorting SQL Query By Date Column

I'm working on a project with a db that contains a date column for patient visits in the format of %m-%d-yyyy and need to sort so that it only pulls the rows where that date is within the last two weeks. I've tried a few different functions of convert, to_date, and can't seem to get anything to work.
I'm still very new to SQL and I don't know if this is a special case because I'm working with an oracle db
Not the full code, because it has dozens of queries and multiple joins (would that affect the date syntax?) but this is the format I'm trying for...
create table "Visits"
insert into "Visits" (
'John Doe',
'5/24/2021',
'Story about the visit',
'More room for story if needed')
select
"User_Name",
"Visit_Date",
"Visit_Narrative",
"Visit_Narrative_Overflow"
from "Visits"
where "Visits"."Visit_Date" >= TRUNC(SYSDATE) - 14
I'm working on a project with a db that contains a date column for patient visits in the format of %m-%d-yyyy
No, you don't have it in the format mm.dd.yyyy. A DATE data type value is stored within the database as a binary value in 7-bytes (representing century, year-of-century, month, day, hour, minute and second) and this has no format.
need to sort so that it only pulls the rows where that date is within the last two weeks.
You want a WHERE filter:
If you want to have the values that happened in the last 14 days then TRUNCate the current date back to midnight and subtract 14 days:
SELECT visit_date
FROM patient
WHERE visit_date >= TRUNC(SYSDATE) - INTERVAL '14' DAY
or
SELECT visit_date
FROM patient
WHERE visit_date >= TRUNC(SYSDATE) - 14
(or subtract 13 if you want today and 13 days before today.)
If you want it after Monday of last week then TRUNCate to the start of the ISO Week (which is always a Monday) and subtract 7 days:
SELECT visit_date
FROM patient
WHERE visit_date >= TRUNC(SYSDATE, 'IW') - INTERVAL '7' DAY
I ended up figuring it out based on an answer from another forum (linked below);
it appears that my original to_date() was incomplete without a second and operator in my where clause. This code is working perfectly
select
"User_Name",
"Visit_Date",
"Visit_Narrative",
"Visit_Narrative_Overflow"
from "SQLUser"."Visits"
where "SQLUser"."Visits"."Visit_Date" >= to_date('5/10/2021', 'MM/DD/YYYY')
and "SQLUser"."Visits"."Visit_Date" < to_date('5/24/2021', 'MM/DD/YYYY')

SQL timestamp filtering based only on time

I want to create a query in Oracle SQL that will grab records from a given time interval, during certain hours of the day, e.g. records between 10am to noon, in the past 10 days. I tried this, but it does not work:
select * from my_table where timestamp between
to_timestamp('2020-12-30','YYYY-MM-DD')
and
to_timestamp('2021-01-08','YYYY-MM-DD') and
timestamp between
to_timestamp('10:00:00','HH24:MI:SS')
and
to_timestamp('12:00:00','HH24:MI:SS')
where timestamp is of type TIMESTAMP. I have also thought of using a join, but I am struggling to find a way to filter on time of day.
Is there a way to filter using only the time, not the date, or a way to filter on time for every day in the interval?
select *
from my_table
where timestamp between to_timestamp('2020-12-30','YYYY-MM-DD')
and to_timestamp('2021-01-08','YYYY-MM-DD')
and timestamp - trunc(timestamp) between interval '10' hour
and interval '12' hour
If you don't need to include exactly noon (including no fractional seconds), you could also do
select *
from my_table
where timestamp between to_timestamp('2020-12-30','YYYY-MM-DD')
and to_timestamp('2021-01-08','YYYY-MM-DD')
and extract( hour from timestamp ) between 10 and 11
As an aside, I'd hope that your actual column name isn't timestamp. It's legal as a column name but it is a reserved word so you're generally much better off using a different name.

Right parenthesis error in oracle SQL Developer

SELECT titol, data_prestec
FROM if_llibres, if_llibre_prestec
WHERE
if_llibre_prestec.ubicacio = if_llibres.ubicacio
AND data_devolucio IS NULL
AND data_prestec <= date_sub(current_date(),interval 30 day);
There is no DATE_SUB() function in Oracle. You could phrase this as:
select
titol,
data_prestec
from if_llibres il
inner join if_llibre_prestec ilp
on ilp.ubicacio = il.ubicacio
where
data_devolucio is null
and data_prestec <= current_date - interval '30' day;
Note that I rewrote your query to use a standard, explicit join (with the on keyword) rather than an implicit join (with a comma in the from clause): this old syntax from decades ago should not be used in new code.
I would also recommend prefixing each column in the SELECT and WHERE clause with the (alias of the) table it belongs to: this makes the query unambiguous and easier to understand.
Subtracting 30 days smells like "previous month". If that was your intention, well, not all months have 30 days so you'll get wrong result. Note that Oracle offers the ADD_MONTHS function which allows you to subtract any number of months. In your case - 1 month.
Furthermore, current_date returns both date and time, so of you subtract 1 month (or 30 days, doesn't matter), you'll move back to that very second, not date itself.
Here's what I mean:
SQL> alter session set nls_Date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select current_date as curdat,
2 current_date - interval '30' day as cur_30,
3 add_months(current_date, -1) as adm_1,
4 --
5 trunc(current_date) - interval '30' day as cur_trun_30,
6 add_months(trunc(current_date), -1) as adm_trun_1
7 from dual;
CURDAT CUR_30 ADM_1 CUR_TRUN_30 ADM_TRUN_1
------------------- ------------------- ------------------- ------------------- -------------------
14.06.2020 21:49:43 15.05.2020 21:49:43 14.05.2020 21:49:43 15.05.2020 00:00:00 14.05.2020 00:00:00
SQL>
CURDAT is current date (along with time)
CUR_30 subtracted 30 days; as you can see, you aren't on 14.05. but 15.05. at 21:49:43 so your query will return rows whose date value depends on that time as well
ADM_1 subtracted 1 month from current date, and it brought you back to 14.05. - again with the time component
CUR_TRUN_30 truncated current date (and "removed" the time component, setting time to midnight at beginning of that day), but you're again at 15.05. - not 14.05.
ADM_TRUN_1 truncated current date and set you to 14.05.2020 00:00 which is - I believe - what you wanted
Therefore, my suggestion would be
SELECT titol,
data_prestec
FROM if_llibres join if_llibre_prestec ON if_llibre_prestec.ubicacio = if_llibres.ubicacio
WHERE data_devolucio IS NULL
AND data_prestec <= ADD_MONTHS(TRUNC(current_date), -1);
Not related to your problems, but I'd suggest you to always use table aliases. The way you wrote the query, it is impossible to know which column belongs to which table and it makes confusion.

Unable to retrieve data for a specific date in SQL

I'm trying to retrieve data for a specific date with query:
Select * from table_1 where activity_date = to_date('13-09-2017','DD-MM-YYYY');
But I'm not getting any result.
But when I query below:
Select * from table_1 where activity_date >= to_date('13-09-2017','DD-MM-YYYY');
I'm getting the data for days greater than equal to 13-09-2017.
Any help?
It seems the data type of your column is Date Time and hence when you are querying with just date (13-09-2017), it searching for date as well as time (13-09-2017 00:00:00). Seems there are no record in your database with this exact date time stamp and hence no results are being returned. Below query will work in your case:
SELECT *
FROM table_1
WHERE activity_date >= to_date('13-09-2017','DD-MM-YYYY')
AND activity_date < to_date('14-09-2017','DD-MM-YYYY');
When you compare dates remember that you usually compare some kind of a timestamp. A timestamp usually also has hours, minutes, seconds etc. So in your database you probably have a whole timestamp like '13-09-2017' + specific hour, minutes and so on, whilst to_date explicitly only formats your DD MM and YYYY causing the hour, minutes and seconds to be equal to 0. The query is probably not returning any records as you probably don't have a date with the exact time equal to 00:00:00.
That's also why a comparison like >= will return results. Because your '13-09-2017' database entries are all greater than '13-09-2017' (with hour equal to 00:00:00) because they all have some hours, minutes and seconds to them, for e.g 13-09-2017 04:02:45 which is greater than 13-09-2017 00:00:00).
How to solve this? Well for example:
SELECT *
FROM table_1
WHERE activity_date >= to_date('13-09-2017','DD-MM-YYYY')
AND activity_date < to_date('14-09-2017','DD-MM-YYYY')