Variable date depending on time - oracle

I got a question. I have a query that will be running as part of a night job. This query is supposed to give me all actions that have taken place during that day. However, and this is the tricky part, it won't always be run on the same time.
Because it is part of a night job, it could happen that on day 1, the query runs at 00:05, and on day 2, it runs on 23:55. This is complicating the query, because I can't say use today's date or use yesterday's date.
I got the following query so far:
select deuda_id from deuda where n_expediente in
(select
(case when to_char(sysdate, 'HH24:MI:SS') between '00:00:00' and '12:00:00' then
(select n_expediente from cartas_enviadas where codigo_carta in ('OIEUR','OIGBP') and f_envio > trunc(sysdate-1)
) else
(select n_expediente from cartas_enviar where codigo_carta in ('OIEUR','OIGBP')
)
) from dual
);
A little explanation: (the database is in Spanish/Italian):
deuda_id is the unique invoice number.
n_expediente is the case number (for this client always unique).
f_envio is the execution date.
codigo_carta is the action type.
Cartas_enviar holds all the actions that are due. When the action is taken, f_envio is entered. Overnight, all actions that have been executed, will be moved from cartas_enviar to cartas_enviadas).
Wat I am trying to do is the following:
I want to look at the current time. If it is before midnight, I want to look at the table cartas_enviar, and take the n_expediente from there, but only if the action is OIEUR or OIGBP. If it is after midnight, I want to look at the table cartas_enviadas, and take the n_expediente from there, but only if the action is OIEUR or OIGBP, and if the action has been executed yesterday.
However, when I am trying to execute this query, I am getting the following error message:
ORA-00905: missing keyword.
Could someone please help me with this query?
PS: It is an Oracle database

The problem is that you can't pull many values like that from subquery of a subquery to pass them back. Try this approach instead:
select deuda_id
from deuda
where
(to_char(sysdate, 'HH24:MI:SS') between '00:00:00' and '12:00:00'
AND n_expediente IN (select n_expediente
from cartas_enviadas
where codigo_carta in ('OIEUR','OIGBP')
and f_envio > trunc(sysdate-1) ))
OR (NOT to_char(sysdate, 'HH24:MI:SS') between '00:00:00' and '12:00:00'
AND n_expediente IN (select n_expediente
from cartas_enviar
where codigo_carta in ('OIEUR','OIGBP')))
;

Related

How can I get the Year to Date (YTD) count of data using Oracle?

How can I get the Year to Date (YTD) count of a certain data using Oracle query?
Assume that we are interested in summing the total number of vouchers filed since the beginning of the current year.
This is the query I came up with
WITH cteDAYSCOUNT AS (SELECT TO_NUMBER(TO_CHAR(SYSDATE, 'DDD'))
FROM dual)
SELECT COUNT(VOUCHER_FILED_DATE), SYSDATE AS "AS OF" FROM CLAIMS
WHERE VOUCHER_FILED_DATE > sysdate - cteDAYSCOUNT;
This part of it returns the number of days since the beginning of the year
WITH cteDAYSCOUNT AS (SELECT TO_NUMBER(TO_CHAR(SYSDATE, 'DDD')) FROM dual)
And this part attempts to use the sysdate - {number of days} to calculate the count
SELECT COUNT(VOUCHER_FILED_DATE), SYSDATE AS "AS OF"
FROM CONTINUED_CLAIMS WHERE VOUCHER_FILED_DATE > sysdate - cteDAYSCOUNT;
But the problem is the although cteDAYSCOUNT holds the number of days since the year starts, it is not being recognized as a number, so it's throws an error
Is there a better query for calculating YTD count or a fix of the above query?
I'm not sure I'm following you.
Query you posted is incomplete; CTE lacks in column name, while FROM clause misses join with the CTE. Therefore, your query can't work at all.
If it is fixed, then:
SQL> WITH
2 ctedayscount (ctedayscount) AS
3 -- this is yours
4 (SELECT TO_NUMBER (TO_CHAR (SYSDATE, 'DDD')) FROM DUAL),
5 claims (voucher_filed_date) AS
6 -- this is my CTE, so that query would actually return something
7 (SELECT DATE '2021-01-15' FROM DUAL)
8 -- final SELECT; you're missing JOIN with CTEDAYSCOUNT
9 SELECT COUNT (voucher_filed_date), SYSDATE AS "AS OF"
10 FROM claims CROSS JOIN ctedayscount
11 WHERE voucher_filed_date > SYSDATE - ctedayscount;
COUNT(VOUCHER_FILED_DATE) AS OF
------------------------- ----------
1 09.02.2021
SQL>
So, it works.
Furthermore, you said:
But the problem is the although cteDAYSCOUNT holds the number of days since the year starts, it is not being recognized as a number, so it's throws an error
How do you know it isn't a NUMBER? Which error is it? It is difficult to debug an unknown error. Could it, perhaps, be that CLAIMS table's voucher_filed_date datatype is something different than DATE (such as VARCHAR2) and contains data which Oracle can't implicitly convert to DATE so WHERE clause (my line #11) fails?
Or is the main problem the fact that you just missed to join CTEDAYSCOUNT with CLAIMS (which I already mentioned)?

How to SELECT the MAX Time Difference Between Any 2 Consecutive Rows Per Value?

Just had a user answer this correctly for TSQL, but wondering how best to achieve this now in SQL Developer/PLSQL seeing as there is no DATEDIFF function.
Table I want to query on has some 'CODE' values, which can naturally have multiple primary key records ('OccsID') in a table 'Occs'. There is also a datetime column called 'CreateDT' for each OccsID.
Just want to find the maximum possible time variance between any 2 consecutive rows in 'Occs', per 'CODE'.
If you subtract the "next" date and "this" date (using the LEAD analytic function), you'll get the date difference. Then fetch the maximum difference per code. Something like this:
with diff as
(select occsid,
code,
nvl(lead(createdt) over (partition by code order by createdt), createdt) - createdt date_diff
from test
)
select code,
max(date_diff)
from diff
group by code;
Assuming that this T-SQL version works for you (from the prior question)
SELECT x.code, MAX(x.diff_sec) FROM
(
SELECT
code,
DATEDIFF(
SECOND,
CreateDT,
LEAD(CreateDT) OVER(PARTITION BY CODE ORDER BY CreateDT) --next row's createdt
) as diff_sec
FROM Occs
)x
GROUP BY x.code
The simplest option is just to subtract the two dates to get a difference in days. You can then multiply to get the difference in hours, minutes, or seconds
SELECT x.code, MAX(x.diff_day), MAX(x.diff_sec)
FROM
(
SELECT
code,
CreateDT -
LEAD(CreateDT) OVER(PARTITION BY CODE ORDER BY CreateDT) as diff_day,
24*60*60* (CreateDT -
LEAD(CreateDT) OVER(PARTITION BY CODE ORDER BY CreateDT)) as diff_sec
FROM Occs
)x
GROUP BY x.code

compare 13digit (millisecond) unix timestamp with date in oracle

A database column (VARCHAR2 datatype) stores the date/time as 13 digit (milliseconds
) unixtimestamp format. Now when I want to compare the column with a oracle date (in question), The error thrown as 'invalid number'
I tried both ways,
converting the 13digit number to Date and compare with the date in question like below. The expressions seems valid as they are printed in select query, but if i include in the where part, it throws 'invalid number'
Here 'value' is 13th digit unixtimestamp column of VARCHAR2 datatype.
select
TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000,
TO_DATE('2014-04-21', 'YYYY-MM-DD')
from dummytable
-- where and TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000 > TO_DATE('2014-04-21', 'YYYY-MM-DD')
converting the date in question to 13digit unixtimestamp and comparing with the database column.The expressions seems valid as they are printed in select query, but if i include in the where part, it throws 'invalid number'
.
select
value,
(to_date('2013-04-21', 'YYYY-MM-DD') - to_date('1970-01-01', 'YYYY-MM-DD')) * (1000*24*60*60)
from dummytable
-- where value > ((to_date('2013-04-21', 'YYYY-MM-DD') - to_date('1970-01-01', 'YYYY-MM-DD')) * (1000*24*60*60))
any pointers? Thanks in advance.
[EDIT- 1 day later] I see the problem now. There are some data (other rows) for the 'value' column that are non-numeric. But I have another column say field, where always field='date' return value as 13 digit timestamp. Now I think when 'where' condition executes, although the field='date' is in the condition, it is still validating the other values for 'value' which are non-numeric. Is there a way to avoid this ?
Your code works just fine. The problem is in your data. Some of your values is not a number.
create table test
(value varchar2(13));
insert into test(value) values('2154534689000');
--insert into test(value) values('2 54534689000');
select TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000
from test
where TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000 > TO_DATE('2014-04-21', 'YYYY-MM-DD');
This code works fine. But if you uncommented the second insert, you would get exactly the same invalid number error as you get.
UPD. Allan gave you a nice hint, but i feel that it can be good to explain you a bit about views. The fact that you select from a view CAN make a difference. A view is not stored somewhere physically, when you select from it, it is just "added to your query". And then Oracle Query Optimizer starts working. Among other things, it can change the order in which your where predicates are evaluated.
For example, your the view query can have a line where value is not null and it would normally show only 'good' values. But if your query has a predicate where to_date(value,'ddmmyyyy') > sysdate, Oracle can decide to evaluate your predicate earlier, because Oracle predicts that it would "cut off" more rows, thus making the whole query faster and less momery consuming. Of course, execution will crash because of an attempt to convert a null string to date.
I believe, that Allan in his answer that he gave a link to, gave a great way to solve this problem: "wrapping" your query in a subquery that Oracle can't "unwrap":
select value
from
(select value
from my_view
where rownum > 0)
where to_date(value,'ddmmyyyy') > sysdate
Hope that helps.

Oracle - Another way for month query?

first... sorry for my english.
I have a query like this:
Select *
From tableA
Where (
TO_NUMBER(TO_CHAR(dateA(+),'SYYYY')) = 2013
AND TO_NUMBER(TO_CHAR(dateA(+),'MM')) = 02
AND to_number(to_char(dateA(+),'dd')) <= 25
)
and retrieve me the data from each date until last number that I give as parameter, in this case the day 25. This working but delay very much because the form of "Where" statement... anybody know another way that retrieve the data so fast and with the same functionality?
It sounds like you want
SELECT *
FROM tableA
WHERE dateA BETWEEN trunc( date '2013-02-26', 'MM' ) AND date '2013-02-26'
This will return all the rows where dateA is between the first of the month and the specified date. If there is an index on dateA, Oracle would be able to use it for this sort of query (though whether it actually would is a separate issue).

Oracle Daily count/average over a year

I'm pulling two pieces of information over a specific time period, but I would like to fetch the daily average of one tag and the daily count of another tag. I'm not sure how to do daily averages over a specific time period, can anyone provide some advice? Below were my first ideas on how to handle this however to change every date would be annoying. Any help is appreciated thanks
SELECT COUNT(distinct chargeno), to_char(chargetime, 'mmddyyyy') AS chargeend
FROM batch_index WHERE plant=1 AND chargetime>to_date('2012-06-18:00:00:00','yyyy-mm-dd:hh24:mi:ss')
AND chargetime<to_date('2012-07-19:00:00:00','yyyy-mm-dd:hh24:mi:ss')
group by chargetime;
The working version of the daily sum
SELECT to_char(bi.chargetime, 'mmddyyyy') as chargtime, SUM(cv.val)*0.0005
FROM Charge_Value cv, batch_index bi WHERE cv.ValueID =97
AND bi.chargetime<=to_date('2012-07-19','yyyy-mm-dd')
AND bi.chargeno = cv.chargeno AND bi.typ=1
group by to_char(bi.chargetime, 'mmddyyyy')
seems like in the first one you want to change the group to the day - not the time... (plus i dont think you need to specify all those 0's for seconds..)
SELECT COUNT(distinct chargeno), to_char(chargetime, 'mmddyyyy') AS chargeend
FROM batch_index WHERE plant=1 AND chargetime>to_date('2012-06-18','yyyy-mm-dd')
AND chargetime<to_date('2012-07-19','yyyy-mm-dd')
group by to_char(chargetime, 'mmddyyyy') ;
not 100% I'm following your question, but if you just want to do aggregates (sums, avg), then do just that. I threw in the rollup just in case that is what you were looking for
with fakeData as(
select trunc(level *.66667) nr
, trunc(2*level * .33478) lvl --these truncs just make the doubles ints
,trunc(sysdate+trunc(level*.263784123)) dte --note the trunc, this gets rid of the to_char to drop the time
from dual
connect by level < 600
) --the cte is just to create fake data
--below is just some aggregates that may help you
select sum(nr) daily_sum_of_nr
, avg(nr) daily_avg_of_nr
, count(distinct lvl) distinct_lvls_per_day
, count(lvl) count_of_nonNull_lvls_per_day
, dte days
from fakeData
group by rollup(dte)
--if you want the query to supply a total for the range, you may use rollup ( http://psoug.org/reference/rollup.html )

Resources