Passing multiple values through a Presentation Variable in a Direct Database Request - obiee

I have created multiple Direct Database Requests in OBIEE, I am able to pass a presentation variable to a Dashboard Prompt. However I am only able to select one value, if I select multiple values, then I get an error saying No results found. I have researched this on the Oracle community but have yet to find a solution, all similar questions have remained unanswered that I found.
When I select multiples values I notice that they are being passed as one long string. eg.
GL_Period IN ('APR-19,AUG-19,FEB-19,JAN-19,JUL-19,JUN-19,MAR-19,MAY-19,NOV-19,OCT-19,SEP-19')
There are beginning and ending quotes instead of quotes around each value.
My Question is can anyone help me get this prompt to accept multiple values. I have tried to update the SQL behind the dashboard prompt, my thinking was that if I concatenate ' to the beginning and end of each value. Then TRIM the first and last ' off that this would work. However I have been unable to get the syntax correct for this, if it is even possible.
Here is the code for my Presentation Variable in my Direct Database Request
AND (
gl_period_name IN ('#{P_Period}')
OR 'All' IN ('#{P_Period}{All}'))
I am able to use the following code to add ' ' to each value - This is for the Presentation Variable P_Period
SELECT CHAR (39)||"Time"."Fiscal Period"||CHAR (39) FROM "Financials - AP Transactions")
I tried the below query to combine the two but to no avail
TO_CHAR(TRIM(BOTH ''' FROM SELECT CHAR (39)||"Time"."Fiscal Period"||CHAR (39) FROM "Financials - AP Transactions"))

Use gl_period_name IN (#{P_Period}['#']{''}) to pass multiple values.
Only problem is this will give you no results if no value is passed (I haven't figured out how to solve that issue yet).

You can turn the comma separated string into multiple values with a Recursive CTE
WITH CTE AS (SELECT 'APR-19,AUG-19,FEB-19,JAN-19,JUL-19,JUN-19,MAR-19,MAY-19,NOV-19,OCT-19,SEP-19' TEMP FROM DUAL)
SELECT TRIM(REGEXP_SUBSTR( TEMP, '[^,]+', 1, LEVEL)) Period FROM CTE
CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(temp, '[^,]+')) + 1
Replacing the hard-coded string with your variable, put that into a sub-query in your where clause and you'll be good to go. Something like this:
select 1 TEST
from dual
where 'APR-19' IN (WITH CTE AS (SELECT 'APR-19,AUG-19,FEB-19,JAN-19,JUL-19,JUN-19,MAR-19,MAY-19,NOV-19,OCT-19,SEP-19' TEMP FROM DUAL)
SELECT TRIM(REGEXP_SUBSTR( TEMP, '[^,]+', 1, LEVEL)) Period FROM CTE
CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(temp, '[^,]+')) + 1)

Related

REGEXP_SUBSTR Remove All Chars after the Match

I am trying to extract Work Weeks from user comments, user comments might be like
"Something WW15 Target Complete"
"WW12.3 Good to Go"
Currently my script is grabbing the match but also everything after it,
Result = WW12.3 Good to Go
Ideal Result would be just the WW12.3 part.
I need to do a course and watch demos on REGEXP but thats for another day unfortunately.
SELECT
BATCH, OPERATOR, COMMENTS, TXN_DATE
,REGEXP_SUBSTR(COMMENTS,'WW[^;]+') as ETA
FROM F_LOTCOMMENTHIST
I have also tried doing this to remove everything after a space but it doesnt work:
SELECT
BATCH, OPERATOR, COMMENTS, TXN_DATE
,REPLACE(REGEXP_SUBSTR(COMMENTS,'WW[^;]+'),' [^;]+','') as ETA
FROM F_LOTCOMMENTHIST
I understand that I am probably using the wrong pattern string but I just cant figure out what I need when looking at example tables like:
https://www.techonthenet.com/oracle/functions/regexp_substr.php
I suggest using an online tester of regular expressions to learn using them.
For example this one: https://regexr.com/5p0m6
You can type your expression and text and you'll see directly the behaviour. Take a look at the cheatsheet and explain section.
Would this do? Oracle, though, I don't know db2.
SQL> with test (col) as
2 (select 'Something WW15 Target Complete' from dual union all
3 select 'WW12.3 Good to Go' from dual union all
4 select 'What is that WW1.2' from dual
5 )
6 select col,
7 regexp_substr(col, 'WW(\w+)?((\.)?(\d+))') result
8 from test;
COL RESULT
------------------------------ ----------
Something WW15 Target Complete WW15
WW12.3 Good to Go WW12.3
What is that WW1.2 WW1.2
SQL>
If you want to get WW[digits][dot][digits] not surrounded by any characters except space (may be), you may use negative lookahead & lookbehind (lookarounds) like below.
with test (col) as
(
values
'SomethingWW15.3 WW12 Target Complete'
, 'WW12.3 Good to Go'
, 'WW12.3What is that WW1.2'
)
select
col
, regexp_substr(col, '(?<![^ ])WW[\d]+\.?[\d]?(?![^ ])') result
from test;
|COL |RESULT|
|------------------------------------|------|
|SomethingWW15.3 WW12 Target Complete|WW12 |
|WW12.3 Good to Go |WW12.3|
|WW12.3What is that WW1.2 |WW1.2 |

I got ORA-00904 when trying to get a list of working days with ORACLE

In my projet I need to use a function called getWorkingDay(beg_date Date,slider Integer). This function is used to find the n-th last working day from the date beg_date (where "n" is the value from slider).
What I would like to do is to get all of the working days within a date range defined by beg_date and end_date. I would like to use a SELECT statement and the function above to get the working days list.
I tried this statement with beg_date=sysdate-45 and end_date=sysdate :
SELECT * FROM(
SELECT getworkingDay(sysdate,slide) dt FROM DUAL
WHERE slide>0 and slide<=sysdate-(sysdate-45))
WHERE dt >=sysdate-45
I got the following error :
ORA-00904 : "SLIDE":invalid identifier
Could you help me to find the way to solve this problem?
Your function, getWorkingDays, only works for one, single date.
If you want it to work for a range of dates, then you need to call it once for each day in the date range.
Using the example from your question, sysdate - 45, means you need to call it 45 times, as in
select getWorkingDays(sysdate - 45, 1) from dual
union
select getWorkingDays(sysdate - 44, 1) from dual
union
select getWorkingDays(sysdate - 43, 1) from dual
I hope you get the idea. I substituted the value 1 (one) for your variable slider. You need to define it as a variable. You claim to be using SQL Developer so I suggest you refer to that product's documentation to see how to define variables.
Alternatively, you could write a SQL query that returns exactly 45 rows (again, 45 because that is the example you used in your question). I believe the following SO question shows how to achieve that:
SQL Query to return N rows from dual
Adapting the answer from that SO question, as well as the example from your question, I believe something like the following should work.
SELECT getWorkingDays(sysdate - (45 - LEVEL), 1)
FROM DUAL
CONNECT BY LEVEL <= 45
Of-course I can't really test it, since I don't have the code for function getWorkingdays().
There is no column name as slide in dual. You need to select from your table which includes the slide column

How to pass more than one string in bind variable in a Oracle Report formula column? [duplicate]

This question already has answers here:
how to convert csv to table in oracle
(5 answers)
Closed 4 years ago.
We’ve got a page that displays a list of records, and the user is allowed to check the desired lines, and then get a report printed of those selected records. I’m trying to define the Oracle Report to have a single parameter which would be a comma-delimited list of the IDs to be printed. However it is not working. The SQL is something like this:
Select * from CEP_TABLE where Table_ID in (:P_IDLIST)
If I define the parameter to be numeric, I get an “invalid parameter input” error when trying to give it 654,655 – it doesn’t like having the comma.
If I define the parameter to be character, it accepts the parameter but then the database gives an “invalid number” error. It appears it is substituting the bind variable with the entire parameter in quotes – e.g.
Select * from CEP_TABLE where Table_ID in (‘654,655’)
But I want it without the quotes:
Select * from CEP_TABLE where Table_ID in (654,655)
I can get the report to work if I define multiple parameters – e.g. Table_ID in (:P1,:P2,:P3,:P4) but they could have a hundred items they want to include so it seems crazy to define 100 parameters – and really… I don’t want any limit.
Has anyone tackled this problem before? – it seems like it would be pretty common. I could have the page write out the selected ids to some temporary table and then define the query to join to that table, but that also seems excessive.
There's a hero that comes to rescue, and his name is lexical parameter.
You said that your query looks like this:
select *
from CEP_TABLE
where Table_ID in (:P_IDLIST)
Report already contains parameter named p_idlist. Now create another one, manually; let's call it lex_idlist. Its datatype should be character, its length somewhat larger than p_idlist parameter's (for example, if p_idlist is character(50), make lex_idlist character(70)).
Then rewrite query as follows:
select *
from cep_table
&lex_idlist
Go to After Parameter Form trigger which should look like this:
function AfterPForm return boolean is
begin
:lex_idlist := 'where table_id in (' || :p_idlist || ')';
return (TRUE);
end;
That's all - compile the report and run it. Enter some values into p_idlist parameter (such as 654,655). The trigger will dynamically create the WHERE clause, store it into the lexical parameter which will then "act" as if it was a real WHERE clause.
Read more about lexical parameters in online Reports Help system.
This is a very common and non-trivial question.
You need to split a single input string into its component tokens. Since I don't have your table, I illustrate how it's done on the emp table in the standard scott schema; here is how you can get the rows for the list of department numbers given in a single comma-separated string, such as '10,30':
select * from scott.emp
where deptno in
(select to_number(regexp_substr(:p_deptno, '\d+', 1, level)) from dual
connect by level <= regexp_count(:p_deptno, '\d+')
)
;
In fairness, there are also methods that don't split the string, and instead play silly games with string comparisons; but those will be quite ineffective - for example they would not allow you to use an index you may have on table_id (or on deptno in my example).

Obtaining a list of date to control file import

I have a need to pull in via FTP only files from dates I haven't pulled data. The data pulls happen nightly, but occasionally there is an issue and a night gets skipped, and it will be picked up the following night.
I located a query on StackOverflow which addressed most of my problem. However, I'm left with an uncomfortable solution and a lingering question.
I have a table with data from each file downloaded. The crux of the data I'm using for this example is EXTRACT_DATE. The file format is filename_20160809.csv, as an example. Uses the 4-digit year, 2-digit month and 2-digit day to make unique. The FTP location has thousands of files, and I only want to grab the new, based on this date.
First, I get the latest EXTRACT_DATE from my table as such
SELECT MAX(EXTRACT_DATE) INTO checkDate FROM FILE_DETAILS;
I had attempted to do this in a single query, but couldn't work it, and finally attempted to create a variable, checkDate, and use this variable in a subsequent query to obtain my list. However, having two queries in a single script is not allowed, or I haven't found a way to do it. So my primary issue is to return the value of the latest date. Then call a new query or procedure with the value incorporated in to obtain my list, with this query
SELECT TO_DATE(checkDate, 'MM/DD/YYYY') + rownum AS EXTRACT_DATES
FROM ALL_OBJECTS
WHERE TO_DATE(checkDate, 'MM/DD/YYYY') + rownum <= TO_DATE(SYSDATE, 'DD-MM-YY');
This solution is messy and uncomfortable, I would prefer a single query to get back my results, rather then 2 scripts or a script and a procedure.
The lingering question, the result from the query returns dates in the mm/dd/yyyy format; 8/9/2016. I adjusted the TO_DATE to match.
Initially, it was set to return as YYYY-MM-DD; 2016-08-09.
However, it wouldn't return in this format. It would only come back as 8/9/2016, regardless of the TO_DATE formatting used. I don't understand why the date is coming back in this format.
SELECT TO_DATE('2-AUG-2016', 'DD-MON-RR') + rownum AS EXTRACT_DATES
FROM ALL_OBJECTS
WHERE TO_DATE('2-AUG-2016', 'DD-MON-RR') + rownum <= TO_DATE(SYSDATE, 'DD-MM-YY');
EXTRACT_DATES
8/3/2016
8/4/2016
8/5/2016
8/6/2016
8/7/2016
8/8/2016
8/9/2016
NLS_DATE_FORMAT is set to DD-MON-RR, with American as NLS_DATE_LANGUAGE.

ORA-00907: missing right parenthesis when create varray

In my program there are a lot of situation when i need to get additional information about knowing ids. So i have list of ids, which length may be very long (for example 100000 elements in it).
How i can use this list and transfer in oracle for getting sql without using temp tables?
No i try to use collection:
CREATE TYPE TEST_VARRAY IS VARRAY(5000) OF NUMBER(18);
SELECT G.ID, G.NAME FROM ANY_TABLE G
WHERE G.ID IN
(
SELECT COLUMN_VALUE FROM TABLE(
NEW TEST_VARRAY
(0,1,2,3... and so on ...,995,996,997,998,999)
)
);
there are 1000 numbers. And when I try execute this query the error ORA-00907: missing right parenthesis tips is appeared! But if i delete first 0 (so we have 999 numbers) the sql is executed ok.
What is problem here?
There is a limit in Oracle IN clause.
A comma-delimited list of expressions can contain no more than 1000
expressions. A comma-delimited list of sets of expressions can contain
any number of sets, but each set can contain no more than 1000
expressions.
Read here or here or here
In my opinion, you are misusing collections, at least I am not sure something like you did is good.
As far as I understand you generate this query before run, so what is the problem to do like that?
with ids as (select /*+ materialize */ 1 id from dual union all
select 2 from dual union all
select 3 from dual union all
select 4 from dual union all
/* repeat with the ids you need */
select 9999 from dual)
select *
from yourTable, ids
where yourTable.id = ids.id;
And that's it! Without any limitations, with pure SQL only. I have added materialize hint to ensure it is not performance relevant, but I think it can be skipped.
No temporary tables, no collections, nothing to create and support. Just SQL.
If you will put ids out of with into from clause it will work in any RDBMS (I guess).

Resources