ORA-00936: missing expression issue - sql

I'm new to oracle sql and I'm trying to run the following query but getting above mentioned error.
SELECT CONVERT(DATETIME,CASE WHEN DATEPART (Hour, OrderTime) < 5
THEN DATEADD(Day, -1, CONVERT(date, ordertime))
ELSE CONVERT(date, ordertime)
END) AS ItemOrderTradingDate FROM TBL_ITEM
Please help.

It seems that you want to extract "hour" from a date column. If that's so, see these two options:
SQL> select ordertime,
2 to_char(ordertime, 'hh24') hour_1,
3 extract(hour from cast(ordertime as timestamp)) hour_2
4 from tbl_item;
ORDERTIME HOUR_1 HOUR_2
------------------- -------- ----------
06.04.2020 08:01:05 08 8
SQL>
Error you got when running Ankint's query was because extract - for certain values (hours, minutes, seconds) works on timestamps, not dates.
I'm not familiar with functions you used (convert, datepart, dateadd) so I can't tell what you really want to do once you find which hour it is. dateadd looks like you'd want to add (or subtract) 1 day from some data value. If that's so, then just do it: date arithmetic is (by default) done by days anyway:
SQL> select sysdate right_now,
2 sysdate + 1 tomorrow,
3 sysdate - 1 yesterday
4 from dual;
RIGHT_NOW TOMORROW YESTERDAY
------------------- ------------------- -------------------
06.04.2020 08:05:34 07.04.2020 08:05:34 05.04.2020 08:05:34
SQL>

You may try below query -
SELECT CASE WHEN EXTRACT(HOUR FROM OrderTime) < 5
THEN TRUNC(ordertime) - 1
ELSE TRUNC(ordertime)
END AS ItemOrderTradingDate
FROM TBL_ITEM

Related

What does Oracle SYSDATE - 1/8 mean?

I am looking at a query:
select JOB_ID from db where last_updated_date >= sysdate - 1/8
I went through the ORACLE SYSDATE documentation but couldn't understand what sysdate - 1/8 means.
Please clarify.
In Oracle, it means you're subtracting 1/8 of the whole day. As one day has 24 hours, its 1/8th part is 24/8 = 3 hours. So:
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select sysdate col1,
2 sysdate - 1/8 col2
3 from dual;
COL1 COL2
------------------- -------------------
29.10.2021 22:18:36 29.10.2021 19:18:36
SQL>
date value remained the same (it is still today, 29.10.2021)
time has changed; right now, it is 22:18:36. When we subtract 3 hours from it, we get 19:18:36 (3 hours earlier)
It means that your query fetches rows whose last_updated_date column value is within the last 3 hours.
It will subtract 3 hours (24 hours/8) from sysdate, try running the following:
select to_char((sysdate - 1/8), 'mm/dd/yyyy hh24:mi:ss') from dual
This will give you 3 hours previous to the current date/time of the database.

SQL - Julien Date (CYYDDD) to date

Unfortunately, this is my first approach with SQL!
I am creating with the following code a query between an oracle DB and Excel (Power Query).
select "$Table"."Order" as "Order",
"$Table"."NR" as "Nr",
"$Table"."JDDATE" as "JDDATE"
from "POOLDB2"."3112" "$Table"
WHERE "Key" >118001
AND "CodeAA" = 1
This code works!
Now I want to format the Julian Date (CYYDDD) - for example 118001 for the 01.01.2019 - to a normal date format.
Does anyone know, how to implement this into the code above?
Maybe something like :
select "$Table"."Order" as "Order",
"$Table"."NR" as "Nr",
DATEADD(DAY, JDDATE % 1000 - 1, DATEADD(year, JDDATE/1000, 0))
"$Table"."JDDATE" as "JDDATE"
from "POOLDB2"."3112" "$Table"
WHERE "Key" >118001
AND "CodeAA" = 1
Best regards
There are many different formats for Julian Date... In your use case, this should do it :
with t as (select 118001 jd from dual)
select to_char( to_date(to_char(1901 + floor(jd / 1000)),'YYYY') + mod(jd,1000) - 1, 'dd.mm.yyyy' ) from t
Yields : 01.01.2019
For Oracle,
select to_char(sysdate,'J') from dual; --To Julian Date
select to_date(2456143,'J') from dual; --To Normal Date
must work.
Edit: Sorry I didn't see oracle tag.
Edit: For the requested behavior by OP
select to_date(to_char(1901 + floor(118001 / 1000)),'YYYY') from dual;
You can use the 118001 value you have, split into separate year and day sections, by adding to the nominal starting date 1900-01-01 (based on your comment that 118001 is actually 2018-01-01, not 2019-01-01):
select date '1900-01-01'
+ floor(118001 / 1000) * interval '1' year
+ (mod(118001, 1000) - 1) * interval '1' day
from dual;
DATE'1900-
----------
2018-01-01
or by startng the fixed date a day earlier you can remove the explicit -1:
select date '1899-12-31'
+ floor(118019 / 1000) * interval '1' year
+ mod(118019, 1000) * interval '1' day
from dual;
DATE'1899-
----------
2018-01-19
This avoids having to build up a longer string to convert to a date, though you could do that (modifying #GMB's approach) as:
select to_date(to_char(1900 + floor(118001 / 1000)) || '-01-01', 'YYYY-MM-DD')
+ (mod(118001, 1000) - 1)
from dual;
You need to specify the month, at least, in the to_date() call as Oracle defaults to the current month if that is not supplied. That behaviour is tucked away in the documentation:
If you specify a date value without a time component, then the default time is midnight. If you specify a date value without a date, then the default date is the first day of the current month.
The first part of that is fairly well known and makes sense ; the second part is a bit less obvious, and doesn't make it clear that it applies to partial dates too - so ifyou don't supply a year then the current year is used; if you don't supply a month then the current month is used; but if you don't supply a day then the 1st is used.
You can see what it's doing with some test conversions:
select to_date('2018-12-25', 'YYYY-MM-DD') as demo_a,
to_date('12:34:56', 'HH24:MI:SS') as demo_b,
to_date('2019', 'YYYY') as demo_c,
to_date('07-04', 'MM-DD') as demo_d,
to_date('2019-01', 'YYYY-MM') as demo_e
from dual;
DEMO_A DEMO_B DEMO_C DEMO_D DEMO_E
------------------- ------------------- ------------------- ------------------- -------------------
2018-12-25 00:00:00 2018-12-01 12:34:56 2019-12-01 00:00:00 2018-07-04 00:00:00 2019-01-01 00:00:00

Oracle: Get Results for everything before 12 am today

WHERE (internalagentname is not null or internalagentcode is not null)
and (source LIKE '%GETAWAY%' or source like '%VACATION%')
and initialbookingdate <= to_Date(to_char(sysdate-1,'MM/DD/YYYY'),
'MM/DD/YYYY')
and (ABS(total_revenue) + ABS(total_cost) + ABS(booking_adjustment))<>0
so, this is my final step query were I am pulling data from yesterdays date. unfortunately its reading this as sysdate - 1 (from current time) so that's why it has data from today current date as well, how can i change this so it only takes out data from 12 am and before? thanks
You should simply be using the logic:
initialbookingdate < trunc(sysdate - 1)
The problem is the <=. The current time has nothing to do with the issue, because there is no time component in the conversion back to a date. Nevertheless, your expression is way more complex than it needs to be.
Saying that you need data that belongs to "yesterday", have a look at this:
SQL> select
2 sysdate right_now,
3 trunc(sysdate) todays_midnight,
4 trunc(sysdate - 1) yesterdays_midnight
5 from dual;
RIGHT_NOW TODAYS_MIDNIGHT YESTERDAYS_MIDNIGHT
------------------- ------------------- -------------------
21.03.2018 21:31:46 21.03.2018 00:00:00 20.03.2018 00:00:00
SQL>
It means that one option is to select values whose initialbookingdate is between "yesterdays_midnignt" and "todays_midnight", i.e.
where initialbookingdate between trunc(sysdate - 1) and trunc(sysdate)
(note that BETWEEN is inclusive).
A simpler option, which would ruin index you might have on initialbookingdate (so - although simpler, use it with caution. On small data amount you wouldn't see problems, but when handling many rows - yes, you would) is
where trunc(initialbookingdate) = trunc(sysdate - 1)
try to use below code in your query condition,
ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YYYY HH:MI:SS AM';
SELECT TRUNC(sysdate)-(.00019/24) date_
FROM dual;
DATE_
----------------------
03/21/2018 11:59:59 PM

How to mask date format in sql?

There is open date 2015-05-19 10:40:14 and close date 2015-05-20 09:21:11
when I subtract them I am getting (close_date.date_value - open_date.date_value)
some 9.45104166666666666666666666666666666667E-01 value
I want to ignore the time 10:40:14 and 09:21:11 from 2 dates
similarly I am subtracting (SYSDATE - open_date.date_value) and get the number of days in number when I subtract 2 dates
Could anyone help me resolving this problem
case
when s then
(close_date.date_value - open_date.date_value)
else
(SYSDATE - open_date.date_value)
end as "dd",
You can use DATEDIFF function. Here is the code
SELECT DATEDIFF(DAY, CONVERT(DATETIME, '2015-05-19 10:40:14'), CONVERT(DATETIME, ' 2015-05-20 09:21:11'))
Try this
case
when status_name.list_value_id=9137981352013344123 then
(TRUNC(close_date.date_value) - TRUNC(open_date.date_value))
else
(TRUNC(sysdate) - TRUNC(open_date.date_value))
end as "e2e execution time",
From performance point of view, I would not use TRUNC as it would suppress any regular index on the date column. I would let the date arithmetic as it is, and ROUND the value.
For example,
SQL> SELECT SYSDATE - to_date('2015-05-20 09:21:11','YYYY-MM-DD HH24:MI:SS') diff,
2 ROUND(
3 SYSDATE - to_date('2015-05-20 09:21:11','YYYY-MM-DD HH24:MI:SS')
4 ) diff_round
5 FROM dual;
DIFF DIFF_ROUND
---------- ----------
29.1248264 29
SQL>

Date difference get different results from function than from select statement

I need to get the difference of 2 date fields, if the greater date is null then I'll use SYSDATE instead. Having this requirement, I created a function to solve this issues (note: this code follows the standard of the organization, not my personal taste)
CREATE FUNCTION F_GET_DIFFERENCE (P_WORKFLOWID NUMBER)
RETURN NUMBER --result in minutes
IS
TIME NUMBER;
BEGIN
TIME := 0
SELECT
F_WORKTIME_DIFF(NVL(X.ENDDATE, SYSDATE), X.STARTDATE)
INTO
TIME
FROM
TABLEX X
WHERE
X.WORKFLOWID = P_WORKFLOWID;
RETURN TIME;
EXCEPTION
WHEN OTHERS THEN
RETURN 0;
END;
The F_WORKTIME_DIFF function already exists and calculates the worktime of the day (assumming nobody works at 12 a.m. and things like that). The problem is when calling this function, the result contains an additional amount of time. That's very strange, because when executing the query in the function, it returns the expected output.
Example (important: date format in Peru is DD/MM/YYYY HH24:MI:SS)
TABLEX
WORKFLOWID STARTDATE ENDDATE
1 '01/12/2012 10:00:00' null
Assumming that the server day is the same day (01/12/2012) but greater time (10:01:00), we execute the function:
SELECT F_GET_DIFFERENCE(1)
FROM DUAL;
The result is: 14.
Now, executing the query in the function and having the server time at 10:02:00, the result is 2 (exact output).
I even tried executing this
SELECT
F_WORKTIME_DIFF(NVL(X.ENDDATE, SYSDATE), X.STARTDATE) SELECT_WAY,
F_GET_DIFFERENCE(1) FUNCTION_WAY
FROM
TABLEX X
WHERE
X.WORKFLOWID = 1
And the result is (having the server time at 10:10:00)
SELECT_WAY FUNCTION_WAY
10 24
Is maybe any consideration that I must take into account when working with Oracle dates in inner functions or anything that could explain this odd behavior?
It is difficult to tell anything without seeing the function F_WORKTIME_DIFF.
Whatever is the datatype returned from F_WORKTIME_DIFF, it is casted to number when assigned to the variable time. This may be a clue.
This may not be exactly what are you looking for but the first example gives you hours diff between two dates:
Select EXTRACT(HOUR FROM (SYSDATE - trunc(SYSDATE )) DAY TO SECOND ) From dual
/
Select
EXTRACT(hour From Cast(SYSDATE as timestamp)) hh,
EXTRACT(minute From Cast(SYSDATE as timestamp)) mi,
EXTRACT(second From Cast(SYSDATE as timestamp)) ss
From dual
/