PostgreSQL and filtered recursive query - oracle

There is an ability to query tree in Oracle with clauses CONNECT BY and START WITH.
For example:
SELECT RPAD (' ', (LEVEL - 1) * 4) || node_name AS node, LEVEL
FROM hierarchy
START WITH NVL (pig_ear_id, 0) = 0
CONNECT BY PRIOR id = pig_ear_id;
The query result can be simply filtered to show the only nodes which accepted by filter predicate or located on the path to root:
SELECT RPAD (' ', (LEVEL - 1) * 4) || node_name AS node, LEVEL
FROM hierarchy
START WITH NVL (pig_ear_id, 0) = 0
CONNECT BY PRIOR id = pig_ear_id AND id IN (
SELECT id
FROM hierarchy
START WITH node_name = 'some-pattern'
CONNECT BY PRIOR pig_ear_id = id
);
A similar select in PostgreSQL will be built with clause WITH RECURSIVE .... As I understand one with-query can not be included in other with-query to get same filtered result as Oracle allows.
How to rewrite the second select in PostgreSQL?..

As I understand one with-query can not be included in other with-query
Of course you can, just write one after the other:
with recursive valid_nodes as (
-- this is the inner "CONNECT BY" query from your example
select id
from hierarchy
where node_name = 'some-pattern'
union all
select c.id
from hierarchy c
join valid_nodes p on c.id = p.pig_ear_id
), final_tree as (
-- this is outer query from your example
select node_name as node, 1 as level
from hierarchy
where NVL (pig_ear_id, 0) = 0
union all
select c.node_name, p.level + 1
from hierarchy c
join final_tree p on p.id = c.pig_ear_id
where id in (select id from valid_nodes) -- and here we re-use the previous CTE
)
select rpad(node, level - 1)||node, level
from final_tree;
Note the recursive keyword only needs to be stated at the beginning. Regardless on how many recursive CTEs you have (but you need to have at least one in the CTE chain, if you use it).

If you have a with query that is calling some function and that function in turn has a with query,
then it allows us and not raise any error...in that way we still able to have nested with query.
so typically i created a query using with clause. see the first query below.
It has in clause which has select query that is selecting records returned by the functions(my_function).
and the function has another hierarchical with query.
Also i do not know what you want to return from your query.so change query as u need.This is just the way to achieve required structure.
Below is the syntax for sql server.Change appropriately for any other database.
with alias_list
(
pig_ear_id,
node_name,
id
) as (
select pig_ear_id, node_name, id
from hierarchy
where pig_ear_id = ?
union all
select b.pig_ear_id, node_name, id
from alias_list a, hierarchy b
where a.pig_ear_id = b.id
and id in (select id from my_function('some-pattern')))
select * from alias_list;
==============================================================
create function my_function(#node_name varchar(40))
returns #temptable table
(
id varchar(40)
)
as
begin
with alias_list
(
pig_ear_id,
node_name,
id
) as (
select pig_ear_id, node_name, id
from hierarchy
where node_name = ?
union all
select b.pig_ear_id, node_name, id
from alias_list a, hierarchy b
where a.id = b.pig_ear_id)
insert into #temptable select * from alias_list;
return
end
================================================================

Related

oracle with as statement , is it possilble to have multiple sub select query

i want to do sub queries , which the data comes from the same selected result . the difference is the xIndex value . code bellow
with src as (
SELECT ROWNUM as xIndex,"LoginResult", ROUND(SYSDATE -"LastLoginTime") as "lastLogonDays"
from "tb_UserStatus"
where "UserId" = userId
ORDER BY "CreateTime" DESC
)
SELECT src."lastLogonDays", src."LoginResult"
into lastLogonDays, hasLogon
from src
where src.xIndex = 1;
SELECT src."lastLogonDays", src."LoginResult"
into reverse2ndDaysDiff, reverse2ndLoginResult
from src
where src.xIndex = 2;
the code block
SELECT src."lastLogonDays", src."LoginResult"
into lastLogonDays, hasLogon
from src
where src.xIndex = 1;
is success.
but , i want another query at the same time
SELECT src."lastLogonDays", src."LoginResult"
into reverse2ndDaysDiff, reverse2ndLoginResult
from src
where src.xIndex = 2;
and it failed.
is it possible the have multiple queries from the same with as result ?
if it is possible , what should do ?
No. A "common table expression" (CTE) does NOT survive after the query that declared it has been completed.
However you can run more than 1 CTE within a query, e.g.:
with src as (
SELECT ROWNUM as xIndex,"LoginResult", ROUND(SYSDATE -"LastLoginTime") as "lastLogonDays"
from "tb_UserStatus"
where "UserId" = userId
ORDER BY "CreateTime" DESC
),
nxtCTE as (
SELECT src."lastLogonDays", src."LoginResult"
--into lastLogonDays, hasLogon
from src
where src.xIndex = 1
)
SELECT src."lastLogonDays", src."LoginResult"
--into reverse2ndDaysDiff, reverse2ndLoginResult
from src
where src.xIndex = 2;
nb: Oracle may use the term "Subquery Factoring" instead of the much more frequently used term "common table expression" - both refer to use of the "with clause". e.g. this page
Whilst CTEs may seem like tables, or "temporary tables", they are not exactly the same as either of those, particularly in that they disappear once the query that created them is complete.
A CTE (WITH clause) is an ad-hoc view valid for only the query to which it belongs. If you want to have a view available for more than one query, store it with CREATE VIEW.
Now let's look at your query:
You are using case-sensitive column names and are thus forced to remember correct case and use quotes. It is not recommended to design your database case-sensitively.
You select from "tb_UserStatus" where "UserId" = userId. So there are two columns called user ID in the table ("UserId" and "USERID")? This sounds like a very bad idea. Did you mean to use a bind variable instead maybe ("UserId" = :userId)? This is not possible in a stored view, though.
You select ROWNUM. This is an arbitrary number indicating in which order Oracle happens to access the rows. It doesn't seem to make much sense to select it.
You have an ORDER BY clause in your view. View results have no order. The clause is superfluous. There are other DBMS that would even report a syntax error here.
And then, what is your incentive? You want to run the same query, but with a different condition? Then you can use a bind variable: where src.xIndex = :xindex;
i have finished it . reference from Paul Maxwell
with src as (
SELECT ROWNUM as xIndex, r.*
from (
SELECT "LoginResult", SYSDATE -"LastLoginTime" as "lastLogonDays"
from "tb_UserStatus"
where "UserId" = userId
ORDER BY "CreateTime" DESC
) r
where ROWNUM < 3
),
lastRcd as (
SELECT src."lastLogonDays", src."LoginResult"
from src
where src.xIndex = 1
)
SELECT src."lastLogonDays", src."LoginResult", lastRcd."lastLogonDays", lastRcd."LoginResult"
into reverse2ndDaysDiff, reverse2ndLoginResult, lastLogonDays, lastLogonResult
from src , lastRcd
where src.xIndex = 2;

Oracle: Value from main query is not available in subquery

I have this query, and one of its column is a subquery that should be bringing a list of values using a listagg function. This list has its starting point as the S.ID_ORGAO_INTELIGENCIA value. The list is a should be, it always has values.
The listagg function is consuming an inline view that uses a window function to create the list.
select *
from (
SELECT DISTINCT S.ID_SOLICITACAO,
S.NR_PROTOCOLO_SOLICITACAO,
S.DH_INCLUSAO,
S.ID_USUARIO,
U.NR_CPF,
OI.ID_MODULO,
OI.ID_ORGAO_INTELIGENCIA,
OI.NO_ORGAO_INTELIGENCIA,
R.ID_ATRIBUICAO,
P.ID_PERMISSAO,
1 AS TIPO_NOTIFICACAO,
(
select LISTAGG(oc6.ID_ORGAO_INTELIGENCIA || '-' || oc6.ord || '-', '; ') WITHIN GROUP (ORDER BY oc6.ord) eai
from (
SELECT oc1.ID_ORGAO_INTELIGENCIA,
oc1.ID_ORGAO_INTELIGENCIA_PAI,
oc1.SG_ORGAO_INTELIGENCIA,
rownum as ord
FROM TB_ORGAO_INTERNO oc1
WHERE oc1.DH_EXCLUSAO is null
-- THE VALUE FROM S.ID_ORGAO_INTELIGENCIA IS NOT AVAILBLE HERE
START WITH oc1.ID_ORGAO_INTELIGENCIA = S.ID_ORGAO_INTELIGENCIA
CONNECT BY prior oc1.ID_ORGAO_INTELIGENCIA_PAI = oc1.ID_ORGAO_INTELIGENCIA
) oc6) aproPrec
FROM TB_SOLICITACAO S
INNER JOIN TB_ORGAO_INTERNO OI ON S.ID_ORGAO_INTELIGENCIA = OI.ID_ORGAO_INTELIGENCIA
INNER JOIN TB_RELACIONAMENTO_ATRIBUICAO R
ON (R.ID_MODULO = OI.ID_MODULO AND R.ID_ORGAO_INTELIGENCIA IS NULL AND
R.ID_SOLICITACAO IS NULL)
INNER JOIN TB_PERMISSAO P
ON (P.ID_USUARIO = :usuario AND P.ID_ORGAO_INTELIGENCIA = :orgao AND
P.ID_ATRIBUICAO = R.ID_ATRIBUICAO)
INNER JOIN TB_USUARIO U ON (U.ID_USUARIO = S.ID_USUARIO)
WHERE 1 = 1
AND U.DH_EXCLUSAO IS NULL
AND P.DH_EXCLUSAO IS NULL
AND S.DH_EXCLUSAO IS NULL
AND OI.DH_EXCLUSAO IS NULL
AND R.ID_ATRIBUICAO IN :atribuicoes
AND P.ID_STATUS_PERMISSAO = 7
AND OI.ID_MODULO = 1
AND S.ID_STATUS_SOLICITACAO IN (1, 2, 5, 6)
and s.ID_ORGAO_INTELIGENCIA in (SELECT DISTINCT o.ID_ORGAO_INTELIGENCIA
FROM TB_ORGAO_INTERNO o
WHERE o.DH_EXCLUSAO IS NULL
START WITH o.ID_ORGAO_INTELIGENCIA = 3
CONNECT BY PRIOR o.ID_ORGAO_INTELIGENCIA = o.ID_ORGAO_INTELIGENCIA_PAI)
);
The problem is that the aproPrec column is always returning null as its result.
If I force the criteria to have the S.ID_ORGAO_INTELIGENCIA hardcoded, the list returns its true value.
If I chance this:
START WITH oc1.ID_ORGAO_INTELIGENCIA = S.ID_ORGAO_INTELIGENCIA
To this:
START WITH oc1.ID_ORGAO_INTELIGENCIA = 311
where 311 is the value that the S.ID_ORGAO_INTELIGENCIA column really has.
Is there a way to make this query works as 'I think' it should work?
To make it work, I changed the subquery by this another one:
(
select qt_.*
from (
SELECT QRY_NAME.*,
rownum as ord
FROM (
SELECT oc1.ID_ORGAO_INTELIGENCIA,
oc1.ID_ORGAO_INTELIGENCIA_PAI,
connect_by_root (oc1.ID_ORGAO_INTELIGENCIA) as root
FROM TB_ORGAO_INTERNO oc1
CONNECT BY NOCYCLE PRIOR oc1.ID_ORGAO_INTELIGENCIA_PAI = oc1.ID_ORGAO_INTELIGENCIA
) QRY_NAME
WHERE root = s.ID_ORGAO_INTELIGENCIA
) qt_
)

can i set up an SSRS report where users input parameters to a table

I have an oracle query that uses a created table as part of the code. Every time I need to run a report I delete current data and import the new data I receive. This is one column of id's. I need to create a report on SSRS in which the user can input this data into said table as a parameter. I have designed a simple report that they can enter some of the id's into a parameter, but there may be times when they need to enter in a few thousand id's, and the report already runs long. Here is what the SSRS code currently says:
select distinct n.id, n.notes
from notes n
join (
select max(seq_num) as seqnum, id from notes group by id) maxresults
on n.id = maxresults.ID
where n.seq_num = maxresults.seqnum
and n.id in (#MyParam)
Is there a way to have MyParam insert data into a table I would join called My_ID, joining as Join My_Id id on n.id = id.id
I do not have permissions to create functions or procedures in the database.
Thank you
You may try the trick with MATERIALIZE hint which normally forces Oracle to create a temporary table :
WITH cte1 AS
( SELECT /*+ MATERIALIZE */ 1 as id FROM DUAL
UNION ALL
SELECT 2 DUAL
)
SELECT a.*
FROM table1 a
INNER JOIN cte1 b ON b.id = a.id

Oracle - What is the order of statement when using functions for filter in where clause

Refer Table WORKQUEUELOG with columns (ID,QueueTypeId,CreateDateTime,WorkId,InQ,OutQ)
There is an index available for (QueueTypeId,CreateDateTime,Id)
When trying to read the first X number of records with following query it is going for a full table search.
OPEN a_CursorHandle FOR
SELECT * FROM (
SELECT * FROM WORKQUEUELOG tbl
WHERE EX_CLS_WQLOG.FILTER(
tbl.QueueTypeId,
tbl.CreateDateTime,
NULL) = 1
AND EX_CLS_WQLOG.VALIDATION(
tbl.ID ,
tbl.WorkId ,
tbl.InQ ) = 1
ORDER BY tbl.QueueTypeId ASC,tbl.CreateDateTime ASC,tbl.Id ASC)
WHERE ROWNUM <= a_MaxCount;
We changed the query as following and started using the index for reading.
ie Validaiton function first and filter function as second.
OPEN a_CursorHandle FOR
SELECT * FROM (
SELECT * FROM WORKQUEUELOG tbl
WHERE EX_CLS_WQLOG.VALIDATION(
tbl.ID ,
tbl.WorkId,
tbl.InQ ) = 1
AND EX_CLS_WQLOG.FILTER(
tbl.QueueTypeId,
tbl.CreateDateTime,
NULL) = 1
ORDER BY tbl.QueueTypeId ASC,tbl.CreateDateTime ASC,tbl.Id ASC)
WHERE ROWNUM <= a_MaxCount;
What is the order of processing the SQL statement in oracle .? left to right or right to left.
From the above example this seems to be right to left . is this a consistent behavior. Is there any other efficient way to write this query.?

Dynamic query in PIVOT IN clause

I need to write a dynamic query inside In clause of pivot query in oracle 11g. With Pivot xml, it is possible, but I do not need the xml one. Here is the code snippet.
WITH pivot_data AS (
select cu.id, u.topic, cu.first_name, cu.last_name, cu.email,
trunc(cu.REGISTRATION_DATE) Register_Date,
trunc(min(u.view_date)) First_Visit,
trunc(max(u.view_date)) Last_Visit,
nvl(sum(u.user_visits),0) Visits,
nvl(sum(u.time_in_topic),0) Time_in_Topic,
ffl.label label, ffv.field_value val
from ACTIVE_USER_VIEWS_BY_TOPIC u
LEFT join cl_user cu
on u.user_id=cu.id
LEFT JOIN CL_PROFILE_FIELD_LABEL ffl
on ffl.cl_customer_accounts_id=cu.cl_customer_accounts_id
LEFT JOIN CL_PROFILE_FIELD_VALUE ffv
on ffl.id = ffv.profile_field_label_id and ffv.user_id= cu.id
LEFT JOIN CL_PROFILE_FIELD_ASSIGNMENT ffa
on ffl.id = ffa.profile_field_label_id
where ffl.cl_customer_accounts_id = (
select cl_customer_accounts_id
from CL_USER where ID = cu.id)
and ffl.ENABLED = 'Y'
and u.PURCHASED_PRODUCT_ID = 582002861
and REGEXP_LIKE (u.topic,
'difficult_interactions|customer_focus|leading_people' )
group by cu.id, u.topic, cu.first_name, cu.last_name, cu.email,
cu.REGISTRATION_DATE, trunc(u.view_date,'MONTH'), ffl.label,
ffv.field_value
)
SELECT *
FROM pivot_data
PIVOT (
max(val)
FOR label
IN ('Flexfield1' AS Flexfield1, 'Flexfield2' AS Flexfield2,
'Flexfield3' AS Flexfield3, 'Flexfield4' AS Flexfield4,
'Flexfield5' AS Flexfield5, 'Flexfield6' AS Flexfield6,
'flexfield021' AS flexfield021, 'sdcs' AS sdcs)
)
I have the query for dynamic data creation i.e.
SELECT DISTINCT
LISTAGG('''' || label || ''' AS ' || label,',')
WITHIN GROUP (ORDER BY label) AS temp_in_statement
FROM (
select distinct label
from cl_profile_field_label
where cl_customer_accounts_id=(
select cl_customer_accounts_id
from cl_purchased_product
where id=582002861));
But if I put the dynamic query inside pivot IN clause, I am getting the error as ORA-00936: missing expression. Please help me out.

Resources