I have a query that is working on oracle 12c but not in 10g. I am not sure what the problem is:
My query is:
WITH tab1(rn,begin_chq_num,chq_lvs_stat,chq_num_of_lvs,tes) AS
(SELECT 1 rn,
begin_chq_num,
chq_lvs_stat,
chq_num_of_lvs,
SUBSTR(chq_lvs_stat,1,1) tes
FROM tbaadm.chq_book_table
WHERE del_flg != 'Y'
AND acid IN
(SELECT acid
FROM tbaadm.GENERAL_ACCT_MAST_TABLE
WHERE foracid = '01411110171546'
)
UNION ALL
SELECT rn + 1 rn,
begin_chq_num,
chq_lvs_stat,
chq_num_of_lvs,
SUBSTR(chq_lvs_stat,rn + 1,1) tes
FROM tab1
WHERE rn < chq_num_of_lvs
)
SELECT
CASE
WHEN begin_chq_num = 1
THEN rn
ELSE begin_chq_num +(rn-1)
END cheque_num,
begin_chq_num
||'-'
||(chq_num_of_lvs+begin_chq_num-1) cheque_range,
DECODE(tes, 'I', 'Issued', 'P', 'Cleared', 'U', 'Unused', 'S', 'Stopped', 'C', 'Cautioned', 'D', 'Destroyed', 'R', 'Returned Paid', 'T', 'Transfered') status
FROM tab1
ORDER BY chq_lvs_stat,
rn;
The error is :
ORA-32033: unsupported column aliasing
32033. 00000 - "unsupported column aliasing"
*Cause: column aliasing in WITH clause is not supported yet
*Action: specify aliasing in defintion subquery and retry
What should I do different?
In Oracle 10g, the sub-query factoring clause does not support column aliases or recursive sub-queries. The syntax you are using appears in 11gR2.
You need to change:
WITH tab1(rn,begin_chq_num,chq_lvs_stat,chq_num_of_lvs,tes) AS
To:
WITH tab1 AS
And find a different solution that does not use a recursive subquery factoring clause.
I think you could do this in Oracle 10g:
WITH tab1 AS (
SELECT l.COLUMN_VALUE rn,
begin_chq_num,
chq_lvs_stat,
chq_num_of_lvs,
SUBSTR(chq_lvs_stat,l.COLUMN_VALUE,1) tes
FROM tbaadm.chq_book_table t,
TABLE(
CAST(
MULTISET(
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= LENGTH( t.chq_lvs_stat )
)
AS SYS.ODCINUMBERLIST
)
) l
WHERE del_flg != 'Y'
AND acid IN ( SELECT acid
FROM tbaadm.GENERAL_ACCT_MAST_TABLE
WHERE foracid = '01411110171546'
)
)
SELECT CASE
WHEN begin_chq_num = 1
THEN rn
ELSE begin_chq_num +(rn-1)
END cheque_num,
begin_chq_num
||'-'
||(chq_num_of_lvs+begin_chq_num-1) cheque_range,
DECODE(
tes,
'I', 'Issued',
'P', 'Cleared',
'U', 'Unused',
'S', 'Stopped',
'C', 'Cautioned',
'D', 'Destroyed',
'R', 'Returned Paid',
'T', 'Transfered'
) status
FROM tab1
ORDER BY chq_lvs_stat, rn;
Related
Hi all I have requirement to pick records using dynamic pivoting in Oracle. I have done with my query which is working fine using "antonsPivoting" https://technology.amis.nl/2006/05/24/dynamic-sql-pivoting-stealing-antons-thunder/.
When i add the query in procedure it gives error: ORA-22905: cannot access rows from a non-nested table item.
Sample table script:
CREATE TABLE DEPARTMENT(DEPT_ID NUMBER PRIMARY KEY, DEPT_NAME VARCHAR2(25))
CREATE TABLE EMPLOYEE(EMP_ID NUMBER, EMP_NAME VARCHAR(100), DEPT_ID NUMBER , FOREIGN KEY(DEPT_ID) REFERENCES DEPARTMENT(DEPT_ID))
INSERT INTO DEPARTMENT(DEPT_ID, DEPT_NAME)
SELECT 1, 'HR' FROM DUAL
UNION ALL SELECT 2, 'OPS' FROM DUAL
UNION ALL SELECT 3, 'MKT' FROM DUAL
UNION ALL SELECT 4, 'FIN' FROM DUAL
UNION ALL SELECT 5, 'IT' FROM DUAL
UNION ALL SELECT 6, 'SERV' FROM DUAL
COMMIT;
INSERT INTO EMPLOYEE(EMP_ID, EMP_NAME, DEPT_ID)
SELECT 1, 'A', 1 FROM DUAL
UNION ALL SELECT 1, 'A', 1 FROM DUAL
UNION ALL SELECT 2, 'B', 1 FROM DUAL
UNION ALL SELECT 3, 'C', 2 FROM DUAL
UNION ALL SELECT 4, 'D', 3 FROM DUAL
UNION ALL SELECT 5, 'E', 3 FROM DUAL
UNION ALL SELECT 6, 'F', 4 FROM DUAL
UNION ALL SELECT 7, 'G', 4 FROM DUAL
UNION ALL SELECT 8, 'H', 4 FROM DUAL
UNION ALL SELECT 9, 'I', 5 FROM DUAL
UNION ALL SELECT 10, 'J', 5 FROM DUAL
UNION ALL SELECT 11, 'K', 1 FROM DUAL
UNION ALL SELECT 12, 'L', 1 FROM DUAL
COMMIT;
sample query script working fine:
SELECT D.DEPT_NAME, COUNT(E.EMP_ID) TOTAL_EMP
FROM DEPARTMENT D
LEFT JOIN EMPLOYEE E ON D.DEPT_ID= E.DEPT_ID
GROUP BY D.DEPT_NAME
;
Dynamic pivoting example working fine:
select * from table( pivot( '
SELECT D.DEPT_NAME, COUNT(E.EMP_ID) TOTAL_EMP
FROM DEPARTMENT D
LEFT JOIN EMPLOYEE E ON D.DEPT_ID= E.DEPT_ID
GROUP BY D.DEPT_NAME' ) )
;
adding in procedure which gives error:
CREATE OR REPLACE PROCEDURE GET_EMPLOYEE (P_RESULT OUT SYS_REFCURSOR)
IS
BEGIN
OPEN P_RESULT FOR
select * from table( pivot( '
SELECT D.DEPT_NAME, COUNT(E.EMP_ID) TOTAL_EMP
FROM DEPARTMENT D
LEFT JOIN EMPLOYEE E ON D.DEPT_ID= E.DEPT_ID
GROUP BY D.DEPT_NAME' ) )
;
END
;
Have you created the Pivot function ?
Please go through below link where this is already answered.
Link
Consider the following sample table:
with v1 as (
select 'I' as parent_id, 'M' as child_id from dual union all
select 'M', 'M1' from dual union all
select 'M', 'D' from dual union all
select 'I', 'P' from dual union all
select 'P', 'K' from dual union all
select 'A', 'P1' from dual union all
select 'C', 'A' from dual union all
select 'A', 'I' from dual union all
select 'P1', 'K1' from dual
)
select ListAgg(child_id,'<-')
within group(order by Level desc) as Path
from v1
START WITH child_id = 'D'
CONNECT BY PRIOR parent_id = child_id;
It returns:
A<-I<-M<-D
It is not returning A's parent which is C.
What should I change in the query so that it returns C as well like below:
C<-A<-I<-M<-D
NOTE that before executing the query, I have no means to know that C is the root of the hierarchy. So, I can not pass C in the query (and that is how I have designed the my query above).
You can use following query:
With v1 as (
select 'C' as parent_id, 'A' as child_id from dual union all
select 'I', 'M' from dual union all
select 'M', 'M1' from dual union all
select 'M', 'D' from dual union all
select 'I', 'P' from dual union all
select 'P', 'K' from dual union all
select 'A', 'P1' from dual union all
select 'A', 'I' from dual union all
select 'P1', 'K1' from dual
)
select ListAgg(case when level =1 then parent_id || '<-' || child_id else parent_id end,'<-')
within group(order by Level desc) as Path
from v1
START WITH child_id = 'D'
CONNECT BY prior parent_id = child_id;
Sqlfiddle demo
Cheers!!
I have an apex item P_USERS which can have a value higher than the amount of rows returning from the query below.
I have a classic report which has the following query:
select
first_name,
last_name
from accounts
where account_role = 'Author'
order by account_nr;
I want placeholder rows to be added to the query (first_name = null, last_name = null etc.), if the total rows from the query is lesser than the value in the apex_item P_USERS.
Any tips on how to achieve this? Maybe with a LEFT join?
If you have more result than the minima you defined, you must add the rest with union.
Here is what you could try to adapt to your case:
SELECT i,c FROM (
select rownum i, c from (
select 'a' c from dual union all select 'b' from dual union all select 'd' from dual union all select 'be' from dual
)), (Select Rownum r From dual Connect By Rownum <= 3)
where (i(+)= r)
union select i,c from (select rownum i, c from (
select 'a' c from dual union all select 'b' from dual union all select 'd' from dual union all select 'be' from dual
)) where i>3
You may try to use a LEFT JOIN.
First, create a list of number until the limit you want like suggested here:
-- let's say you want 300 records
Select Rownum r From dual Connect By Rownum <= 300
Then you can use this to left join and have empty records:
SELECT C, R FROM
( select rownum i, c from (select 'a' c from dual union all select 'b' from dual) )
, ( Select Rownum r From dual Connect By Rownum <= 300)
where i(+)= r order by r
The above gives you an ordered list starting with 'a', 'b', then null until the end.
So you could adapt it to your case so:
SELECT F,L FROM
( select rownum i, f, l from (
select first_name f, last_name l
from accounts where account_role = 'Author'
order by account_nr) )
, ( Select Rownum r From dual Connect By Rownum <= 300)
where i(+)= r
I have a source table which contains values as :
Col1 Col2
A B
B C
E F
F G
G H
X Y
In this scenario A is a parent and b is child of A
And C is a grand child of A, parent and it's child with grand child's should come in one single line.
So the expected output is
Output :
A B C
E F G H
X Y
Oracle 11gR2 Setup:
CREATE TABLE table_name ( Col1, Col2 ) AS
SELECT 'A', 'B' FROM DUAL UNION ALL
SELECT 'B', 'C' FROM DUAL UNION ALL
SELECT 'E', 'F' FROM DUAL UNION ALL
SELECT 'F', 'G' FROM DUAL UNION ALL
SELECT 'G', 'H' FROM DUAL UNION ALL
SELECT 'X', 'Y' FROM DUAL;
Query:
SELECT SUBSTR( SYS_CONNECT_BY_PATH( Col1, ' ' ) || ' ' || Col2, 2 ) AS path
FROM table_name
WHERE CONNECT_BY_ISLEAF = 1
START WITH Col1 NOT IN ( SELECT Col2 FROM table_name )
CONNECT BY PRIOR Col2 = Col1;
Explanation:
Start (line 4) with each Col1 where there is not a parent row identified by a corresponding Col2 value and create a hierarchical query connecting (Line 5) Col1 the the prior parent row.
Filter the output only to those rows which are a leaf of the hierarchical tree (line 3) - i.e. those with no children.
You can then use SYS_CONNECT_BY_PATH to generate a string containing all the Col1 values from the root to the leaf of each branch of the tree generated by the hierarchy and concatenate that with the final Col2 value at the leaf. SUBSTR is used to remove the leading space delimiter that SYS_CONNECT_BY_PATH prepends to each entry in the path.
Output:
PATH
-------
A B C
E F G H
X Y
Is it what you search for?
SQL> with
2 src as (select 'A' p#, 'B' c# from dual union all
3 select 'B' p#, 'C' c# from dual union all
4 select 'E' p#, 'F' c# from dual union all
5 select 'F' p#, 'G' c# from dual union all
6 select 'G' p#, 'H' c# from dual union all
7 select 'X' p#, 'Y' c# from dual)
8 select
9 max(trim(sys_connect_by_path(p#, ' ') || ' ' || c#)) r#
10 from
11 src
12 start with
13 p# not in (select c# from src)
14 connect by p# = prior c#
15 group by connect_by_root(p#);
R#
--------------------------------------------------------------------------------
A B C
X Y
E F G H
May be this code can help you.
WITH t1(id, parent_id) AS (
-- Anchor member.
SELECT id,
PARENT
FROM table
WHERE id = 'A'
UNION ALL
-- Recursive member.
SELECT t2.id,
t2.PARENT
FROM table t2, table t1
WHERE t2.PARENT = t1.id
)
SELECT id, parent_id
FROM t1;
Below is my sql query and I am getting error while executing it as ORA-01427: single-row subquery returns more than one row.
Please help with a work around:
SELECT *
FROM TableName err
WHERE ERR.SYSCD IN
(decode(REGEXP_COUNT('TEST1,TEST2', ','), 0, 'TEST3',
(SELECT DISTINCT syscd
FROM TableName
WHERE syscd IN
(SELECT err.syscd
FROM TableName ERR
WHERE ERR.SYSCD NOT IN
(SELECT UPPER(
REGEXP_SUBSTR(
'TEST1',
'[^,]+',
1,
LEVEL))
CNTRY_CD
FROM DUAL
CONNECT BY REGEXP_SUBSTR(
'TEST1',
'[^,]+',
1,
LEVEL)
IS NOT NULL)
)
OR syscd IS NULL)))
Its a simple misconception. Here is how decode works:
select decode(a, 'a', 'AA', 'b','BB', '??') from (
select 'a' a from dual
union all select 'b' a from dual
union all select 'c' a from dual
);
gives
AA
BB
??
This is because every operand in decode is a single value. But in your query, it is obvious your
SELECT DISTINCT syscd
FROM TableName
WHERE syscd IN (<some values set>)
OR syscd IS NULL
returns more than one row. So to solve it, you should ensure there is only one row with a WHERE rownum=1:
SELECT *
FROM TableName err
WHERE ERR.SYSCD IN
(decode(REGEXP_COUNT('TEST1,TEST2', ','), 0, 'TEST3',
select val from (SELECT DISTINCT syscd val
FROM TableName
WHERE syscd IN
(SELECT err.syscd
FROM TableName ERR
WHERE ERR.SYSCD NOT IN
(SELECT UPPER(
REGEXP_SUBSTR(
'TEST1',
'[^,]+',
1,
LEVEL))
CNTRY_CD
FROM DUAL
CONNECT BY REGEXP_SUBSTR(
'TEST1',
'[^,]+',
1,
LEVEL)
IS NOT NULL)
)
OR syscd IS NULL) where rownum=1))
Be careful, because this might not do what you expect. It only takes one value from the sub-select, but not sure it is what you expect.
EDIT
It makes no sense to do the above for you. What you want, is have either syscd in <one set>, and possibly in other values from your decode. So make an union between them; Here:
SELECT *
FROM TableName err
WHERE ERR.SYSCD IN (
select decode(REGEXP_COUNT('TEST1,TEST2', ','), 0, 'TEST3')
from dual
union
SELECT DISTINCT syscd
FROM TableName
WHERE syscd IN
(SELECT err.syscd
FROM TableName ERR
WHERE ERR.SYSCD NOT IN
(SELECT UPPER(
REGEXP_SUBSTR(
'TEST1',
'[^,]+',
1,
LEVEL))
CNTRY_CD
FROM DUAL
CONNECT BY REGEXP_SUBSTR(
'TEST1',
'[^,]+',
1,
LEVEL)
IS NOT NULL)
)
OR syscd IS NULL)
... but it still doesn't make much sense...