Getting rid of the time in a date - sql

SELECT close_date, close_UIN, count(*) as Amount_Closed_per_employee
FROM t_return_master
where status = 'C' AND TO_DATE (close_date ,'DD-MON-YY') BETWEEN TO_DATE
('~Date From~', 'DD/MM/YYYY') AND TO_DATE('~Date To~','DD/MM/YYYY')
group by close_date, close_UIN
order by close_UIN
I have the code you see above, at the moment it displays the hours, minutes and seconds when it displays the close date, however as I am grouping by close date, I need this to go so it group by date only. Anyone any ideas how I can do this?

You can use TRUNC() on the date (in the SELECT and GROUP BY clauses) which, with just the default argument, sets the hours/minutes/seconds/milliseconds to zero.
SELECT TRUNC( close_date ) AS close_date_day,
close_UIN,
count(*) as Amount_Closed_per_employee
FROM t_return_master
where status = 'C'
AND TO_DATE (close_date ,'DD-MON-YY')
BETWEEN TO_DATE('~Date From~', 'DD/MM/YYYY')
AND TO_DATE('~Date To~','DD/MM/YYYY')
group by TRUNC( close_date ), close_UIN
order by close_UIN

The simplest way is to use the trunc() function, which by default sets the time portion of the date value to midnight:
SELECT trunc(close_date), close_UIN, ...
...
group by trunc(close_date), close_UIN
order by close_UIN
Note that you need to truncate the value in the select list and the group-by clause. The function can optionally truncate to a different precision too, like removing seconds, or going to the first day of the month, etc.:
select sysdate, trunc(sysdate), trunc(sysdate, 'SS') from dual;
SYSDATE TRUNC(SYSDATE) TRUNC(SYSDATE,'MI')
------------------- ------------------- -------------------
2015-05-01 09:37:48 2015-05-01 00:00:00 2015-05-01 09:37:00
See the docs for more info.
This is not correct:
AND TO_DATE (close_date ,'DD-MON-YY') BETWEEN TO_DATE
('~Date From~', 'DD/MM/YYYY') AND TO_DATE('~Date To~','DD/MM/YYYY')
Since close_date is already a date column you're doing an implicit conversion to a string using your NLS_DATE_FORMAT, and then an explicit conversion back to a date using 'DD-MON-YY' - which is using a two-digit year and will cause its own problems. The behaviour may vary for other users with different settings.
It looks like you're trying to do the equivalent of a trunc() to make the between cover the whole of the final day, but you won't get the year (century) you expect. And calling any function on the column will prevent any index on it being used, unless you have a matching function-based index (but using trunc() only in the select list and group by is OK).
If you want all records from the start of 'date from' to the end of 'date to' you can specify that with a range instead of 'between' - which is inclusive but might not get the result you expect depending on your NLS settings, again. Something like:
AND close_date >= TO_DATE('~Date From~', 'DD/MM/YYYY')
AND close_date < TO_DATE('~Date To~','DD/MM/YYYY') + 1
Less than midnight on the day after 'date to' is equivalent to saying up to 23:59:59 on 'date to', i.e. covering that entire day.

Related

ORACLE SQL SYSDATE and between

I am trying to get a date using between SYSDATE and SYSDATE - 300.
SELECT date_entered
FROM customer_order_join
WHERE TO_CHAR(date_entered, 'YYYYMMDD') BETWEEN
TO_DATE(sysdate, 'YYYYMMDD') AND TO_DATE(sysdate, 'YYYYMMDD') - 300
I am getting the following error :
ORA-01858: a non-numeric character was found where a numeric was expected.
SYSDATE returns a DATE value. Never run TO_DATE() on a value which is already a DATE. Apart from that, BETWEEN ... AND requires the lower date first.
You can compare the DATE values directly, I guess you are looking for this:
SELECT DATE_ENTERED
FROM CUSTOMER_ORDER_JOIN
WHERE DATE_ENTERED Between SYSDATE-300 AND SYSDATE
Most likely you like to compare just the date values, without time value. Then you could use this:
SELECT DATE_ENTERED
FROM CUSTOMER_ORDER_JOIN
WHERE TRUNC(DATE_ENTERED) Between TRUNC(SYSDATE-300) AND TRUNC(SYSDATE) -- or TRUNC(SYSDATE)+1 to cover full day
Note, the query will not utilize an index on DATE_ENTERED, unless you have a function-based index on TRUNC(DATE_ENTERED). So you may prefer
SELECT DATE_ENTERED
FROM CUSTOMER_ORDER_JOIN
WHERE DATE_ENTERED >= TRUNC(SYSDATE-300)
AND DATE_ENTERED < TRUNC(SYSDATE)
There is some strange date conversions in your where clause:
To_Char(DATE_ENTERED, 'YYYYMMDD')
If the column is already a date type just use the column without any conversions and if it is a string, use TO_DATE.
TO_DATE(SYSDATE,'YYYYMMDD')
No conversion needed
TO_DATE(SYSDATE,'YYYYMMDD')-300
No conversion needed
So maybe just:
SELECT DATE_ENTERED FROM CUSTOMER_ORDER_JOIN
WHERE TRUNC(DATE_ENTERED) Between TRUNC(SYSDATE - 300) AND TRUNC(SYSDATE);

Filtering a dataset by date and time Oracle SQL through Power BI

I'm having trouble with filtering a date and time for anything two hours before and sooner. I tried this:
SELECT *
FROM
table
where
date >= sysdate - 1
AND
TO_DATE( Time, 'HH24:MI:SS' ) >= TO_DATE( sysdate, 'HH24:MI:SS' ) - 2
But I'm getting an inconsistent type error which is what I thought I was handling with the TO_DATE() function but I guess not.
sysdate is already a date (and time), so TO_DATE( sysdate, 'HH24:MI:SS' ) doesn't make any sense.
You didn't provide your data types for your date and time columns in table, so I'm going to assume they're both varchar2(10) with formats MM/DD/YYYY and HH24:MI:SS respectively.
I'm also going to go ahead and change your example table and column names, since they're invalid names to use in a real query.
-- example data
with my_table as (select '06/13/2019' as date_column, '09:40:34' as time_column from dual)
-- your query
SELECT *
FROM
my_table
where
to_date(date_column || ' ' || time_column, 'MM/DD/YYYY HH24:MI:SS') >= sysdate - 2/24
What I'm doing here is to combine your date and time strings into one date-time string, then converting it to an Oracle date type (actually date+time). Then we compare it to sysdate - 2/24, which says to take the current time and subtract 2/24ths of a day, which is 2 hours.
For this example, you might need to change the example data date_column and time_column values to something from the past 2 hours, depending on when you run this and what time zone you're in.

Sql Change Time in Query

I currently have the following Problem, working on an Oracle Database:
I have 2 columns of an appointment I want to read: date_from and date_to. They have both DateTime as the datatype.
I need to adjust the time of the value though (and only the time, the date should stay the same).
date_from for example contains 10.10.2017 14:21:00 as a value,
but should be changed to the "start of the day" --> 10.10.2017 00:00:00
date_to for example contains 11.10.2017 11:47:00 as a value,
but should be changed to the "end of the day" --> 10.10.2017 23:59:59
Is this somehow possible to manipulate it this way? I can not do an Update or permanent change to the data. This Format is only needed for a Gantt Diagramm, I dont have an other way to change it.
Thank you in Advance!
Yes, you can achieve that with Oracle's TO_DATE and TO_CHAR functions. It will only depend if you need the result as a DATE or as a VARCHAR. The syntax would look like this for VARCHAR output:
TO_CHAR(date_from, 'DD.MM.YY') || ' 00:00:00'
TO_CHAR(date_to, 'DD.MM.YY') || ' 23:59:59'
If you need the DATE value from this, just add the TO_DATE funtion around it:
TO_DATE((TO_CHAR(date_from, 'DD.MM.YY') || ' 00:00:00'), 'DD.MM.YY HH24:MI:SS')
TO_DATE((TO_CHAR(date_to, 'DD.MM.YY') || ' 23:59:59'), 'DD.MM.YY HH24:MI:SS')
I did not test it, but it's pretty much it.
Does this helps?
Cheers
Nikao
If you need to show the result, try this:
select to_char(date_from, 'DD.MM.YYYY') ||' 00:00:00' as date_from,
to_char(date_to, 'DD.MM.YYYY') ||' 23:59:59' as date_to
from table_name
But you may need to compare intervals. In this case, you could discarts the time using trunc function:
select *
from table_dates t,
other_table o
where trunc(o.some_date) between trunc(t.date_from) and trunc(t.date_to)
UPD: First, I did an implicit conversion of dates to string using TRUNC. But it can lead to inexpected result. Instead, explicitly use TO_CHAR with the format model you are expecting for your output and you do not need to use TRUNC. (Thank you #MT0 )
So you want to return the start and end of the day?
select trunc(start_date) as day_start, -- Strips off the time part of the date
trunc(end_date) + 1 - (1/86400) as day_end -- As above, but we add 1 day and minus 1 second
from My_Table
Also, Oracle has date formats of Date and Timestamp, no datetime
this might be some help to you:
SELECT to_char(current_timestamp,'yyyy-mm-dd hh:mm:ss') FROM dual;
SELECt trunc(current_timestamp)||' 23:59:59' FROM dual;

When and why does the TRUNC(DATE, [FORMAT]) used in the real world

I am getting into Oracle database. I came across the TRUNC(DATE, [FMT]) function. I am not really clear on it except it seems to return the beginning value of some sort?
Can somebody educate me on it? When or what would it be used for at work, or why somebody might want to use the function?
Try this query to know when it might be usefull:
ALTER SESSION SET NLS_DATE_FORMAT = 'yyyy-mm-dd hh24:mi:ss';
select sysdate,
trunc( sysdate, 'mi' ) As beginning_of_current_minute,
trunc( sysdate, 'mi' ) As beginning_of_current_hour,
trunc( sysdate, 'dd' ) As beginning_of_current_day,
trunc( sysdate, 'iw' ) As beginning_of_current_week,
trunc( sysdate, 'mm' ) As beginning_of_current_month,
trunc( sysdate, 'q' ) As beginning_of_current_Quarter,
trunc( sysdate, 'y' ) As beginning_of_current_Year
FROM dual;
An example - you want to get all orders starting from the beginning of the current week:
SELECT *
FROM ORDERS
WHERE order_date >= trunc( sysdate, 'iw' )
A real world example would be if you wanted to aggregate results from a table by year. You could use the TRUNC function like this:
SELECT TRUNC(my_date, 'YEAR') the_year, count(*)
FROM some_table
GROUP BY TRUNC(my_date, 'YEAR');
...which would return a set of results with the first column the date truncated to the beginning of the year and the second column a count of all the records with dates within that year.
the_year, count(*)
_________________
01-JAN-12, 543
01-JAN-13, 1268
01-JAN-14, 1134
01-JAN-15, 1765
There are obviously other ways to achieve the same thing, but this is a real world example of how you might use TRUNC.
Another might be if you are comparing dates and you only want to use a certain degree of precision. If you have a timestamp column and you want all the records for today, you could select based on a range where the timestamp is greater than midnight yesterday and less than midnight today, or you could select where the timestamp, truncated to the DATE, is equal to today.
https://docs.oracle.com/cd/E29805_01/server.230/es_eql/src/cdfp_analytics_lang_trunc.html
Another thing it is useful for is to get the time component of the current day. I use an expression like this all the time:
SELECT sysdate - trunc(sysdate) AS TodaysTime FROM DUAL
Because the system date is stored in a decimal format (e.g. sysdate = 42651.2426897456) and the integer value corresponds to midnight, I can use the above statement to get only the decimal portion (e.g. TodaysTime = 0.2426897456, or just before 6 AM).
There may be easier ways to do this, but in my applications this has been the easiest as I frequently need to work with only the day's time component.

Oracle SQL comparison of DATEs returns wrong result

I have REPORTDATE column in database (DATETIME) type.
I want to extract only DATE value from the DATETIME, then to do COUNT for each day and to put WHERE clause to restrict only dates later than some specific date.
So I have this clause:
SELECT to_char(REPORTDATE, 'DD.MM.YYYY') AS MY, COUNT(*) from INCIDENT
where to_char(REPORTDATE, 'DD.MM.YYYY')>'09.11.2013'
GROUP BY to_char(REPORTDATE, 'DD.MM.YYYY')
It returns me results but but I can notice wrong result such as : 30.10.2013 which is wrong result.
How to solve this?
WHERE to_char(REPORTDATE, 'DD.MM.YYYY')>'09.11.2013'
You are comparing two STRINGS. You need to compare the DATEs. As I already said in the other answer here, you need to leave the date as it is for DATE calculations. TO_CHAR is for display, and TO_DATE is to convert a string literal into DATE.
SELECT TO_CHAR(REPORTDATE, 'DD.MM.YYYY'),
COUNT(*)
FROM TABLE
WHERE REPORTDATE > TO_DATE('09.11.2013', 'DD.MM.YYYY')
GROUP BY TO_CHAR(REPORTDATE, 'DD.MM.YYYY')
Also, REPORTDATE is a DATE column, hence it will have datetime element. So, if you want to exclude the time element while comparing, you need to use TRUNC
WHERE TRUNC(REPORTDATE) > TO_DATE('09.11.2013', 'DD.MM.YYYY')
However, applying TRUNC on the date column would suppress any regular index on that column. From performance point of view, better use a Date range condition.
For example,
WHERE REPORTDATE
BETWEEN
TO_DATE('09.11.2013', 'DD.MM.YYYY')
AND
TO_DATE('09.11.2013', 'DD.MM.YYYY') +1
The condition to_char(REPORTDATE, 'DD.MM.YYYY')>'09.11.2013' compare to strings, so 30.10.2013 is after 09.11.2013.
You need to compare the dates, not the string values, so you have to change your query to the following.
SELECT to_char(REPORTDATE, 'DD.MM.YYYY') AS MY, COUNT(1)
from INCIDENT
where trunc(REPORTDATE)> to_date('09.11.2013', 'DD.MM.YYYY')
GROUP BY to_char(REPORTDATE, 'DD.MM.YYYY')
Note: I added a little modification from count(*) to count(1) for optimize the query having the same results.