Want to generate o/p as Below in Oracle - oracle

I need an o/p as below.
1,1
2,1
2,2
3,1
3,2
3,3
4,1
4,2
4,3
4,4
... and so on.
I tried to write the query as below. But throwing error. SIngle row subquery returns more than one row.
with test1 as(
SELECT LEVEL n
FROM DUAL
CONNECT BY LEVEL <59)
select n,(
SELECT LEVEL n
FROM DUAL
CONNECT BY LEVEL <n) from test1
Appreciate your help in solving the same.

Here is one of the methods how you could get the desired result:
SQL> with t1(col) as(
2 select level
3 from dual
4 connect by level <= 5
5 )
6 select a.col
7 , b.col
8 from t1 a
9 join t1 b
10 on a.col >= b.col
11 ;
COL COL
---------- ----------
1 1
2 1
2 2
3 1
3 2
3 3
4 1
4 2
4 3
4 4
5 1
5 2
5 3
5 4
5 5
15 rows selected

Related

How to generate oracle rank and dense_rank function in Talend?

SQL> select ID,rank() over(order by ID) RANK , dense_rank() over(order by ID) DENSE_RANK from a;
ID RANK DENSE_RANK
1 1 1
1 1 1
2 3 2
3 4 3
3 4 3
4 6 4
5 7 5
5 7 5
6 9 6
7 10 7

BigQuery: straight table format of matrix multiplication into more traditional Matrix multiplication format?

This question here shows how to get matrix multiplication into straight table format, for example given (6x1) (Path, value) matrix, you will get (36,1) straight table. Now I want to get the traditional matrix multiplication format, in the example it would be (6x6) matrix.
How to shape a straight table of matrix multiplication into more traditional matrix multiplication format?
--standardSQL
WITH MatrixA AS (
SELECT 1 AS p, 2 AS val UNION ALL
SELECT 2, -3 UNION ALL
SELECT 3, 4 UNION ALL
SELECT 4, -1 UNION ALL
SELECT 5, 0 UNION ALL
SELECT 6, 2
), MatrixB AS (
SELECT 1 AS p, -1 AS val UNION ALL
SELECT 2, 2 UNION ALL
SELECT 3, 3 UNION ALL
SELECT 4, 3 UNION ALL
SELECT 5, 0 UNION ALL
SELECT 6, 1
),
matrixMultiplication AS
(
SELECT a.p AS ap, b.p as bp, SUM(a.val * b.val) val
FROM MatrixA AS a
CROSS JOIN MatrixB AS b
GROUP BY a.p, b.p
ORDER BY a.p, b.p
)
--36 elements for the 6x6 PATHS Matrix
--TODO: how to shape it to 6x6 matrix?
SELECT * FROM matrixMultiplication
how to shape it to 6x6 matrix?
Below is for BigQuery Standard SQL. Few simple options
Option #1
#standardSQL
SELECT ap AS row, STRING_AGG(CAST(val AS STRING), ' ' ORDER BY bp) AS cols
FROM matrixMultiplication
GROUP BY row
-- ORDER BY row
when applied to dummy data from your question - result is
Row row cols
1 1 -2 4 6 6 0 2
2 2 3 -6 -9 -9 0 -3
3 3 -4 8 12 12 0 4
4 4 1 -2 -3 -3 0 -1
5 5 0 0 0 0 0 0
6 6 -2 4 6 6 0 2
Option #2
#standardSQL
SELECT row,
cols[OFFSET(0)] AS col1,
cols[OFFSET(1)] AS col2,
cols[OFFSET(2)] AS col3,
cols[OFFSET(3)] AS col4,
cols[OFFSET(4)] AS col5,
cols[OFFSET(5)] AS col6
FROM (
SELECT ap AS row, ARRAY_AGG(val ORDER BY bp) AS cols
FROM matrixMultiplication
GROUP BY ap
)
-- ORDER BY row
when applied to dummy data from your question - result is
Row row col1 col2 col3 col4 col5 col6
1 1 -2 4 6 6 0 2
2 2 3 -6 -9 -9 0 -3
3 3 -4 8 12 12 0 4
4 4 1 -2 -3 -3 0 -1
5 5 0 0 0 0 0 0
6 6 -2 4 6 6 0 2

Oracle Connect By seems to produce too many rows

Oracle Database 12c Enterprise Edition Release 12.1.0.2.0
I expect I'm just missing something, but if I run this query without the "connect by", I get 2 rows. When I add "connect by level <= 4", I would expect to get each of those 2 rows 4 times. The actual result is different.
Can anyone help me understand what's happening here? I'm not looking for a solution that only repeats each row 4 times - I've already got that. I'm just looking to understand what's happening and why.
with alpha as (
select 1 as id
from dual
),
beta as (
select 1 as alpha_id,
1 as beta_no
from dual
union all
select 1 as alpha_id,
2 as beta_no
from dual
)
select a.id,
b.beta_no,
level as the_level
from alpha a
inner join beta b
on b.alpha_id = a.id
connect by level <= 4
order by a.id,
b.beta_no,
level
;
ID BETA_NO THE_LEVEL
1 1 1
1 1 2
1 1 2
1 1 3
1 1 3
1 1 3
1 1 3
1 1 4
1 1 4
1 1 4
1 1 4
1 1 4
1 1 4
1 1 4
1 1 4
1 2 1
1 2 2
1 2 2
1 2 3
1 2 3
1 2 3
1 2 3
1 2 4
1 2 4
1 2 4
1 2 4
1 2 4
1 2 4
1 2 4
1 2 4
30 rows selected
Many thanks to mathguy. The second link he provided in the answer below had exactly what I was looking for. Specifically:
1 with t as (select 1 as id from dual union all
2 select 2 from dual)
3 --
4 select id, level
5 ,prior id
6 ,sys_connect_by_path(id,'=>') as cpath
7 from t
8* connect by level <= 3
SQL> /
ID LEVEL PRIORID CPATH
---------- ---------- ---------- --------------------------------------------------
1 1 =>1
1 2 1 =>1=>1
1 3 1 =>1=>1=>1
2 3 1 =>1=>1=>2
2 2 1 =>1=>2
1 3 2 =>1=>2=>1
2 3 2 =>1=>2=>2
2 1 =>2
1 2 2 =>2=>1
1 3 1 =>2=>1=>1
2 3 1 =>2=>1=>2
2 2 2 =>2=>2
1 3 2 =>2=>2=>1
2 3 2 =>2=>2=>2
14 rows selected.
It's clear to me from that example, but I'd be hard-pressed to succinctly put it into words.
With no condition other than "level <= 4", every row from the original table, view etc. (from the join, in this case) will produce two rows at level 2, then four more rows at level 3, and 8 more at level 4. "Connect by" is essentially a succession of joins, and you are doing cross joins if you have no condition with the PRIOR operator.
You probably want to add "and prior a.id = a.id". This will lead to Oracle complaining about cycles (because Oracle decides a cycle is reached when it sees the same values in the columns subject to PRIOR). That, in turn, is solved by adding a third condition, usually "and prior sys_guid() is not null".
(Edited; the original answer made reference to NOCYCLE, which is not needed when using the "prior sys_guid() is not null" approach.)
This has been discussed recently on OTN: https://community.oracle.com/thread/3999985
Same question discussed here: https://community.oracle.com/thread/2526535
To illustrate Mathguy's answer, you are missing some predicates out of your CONNECT BY clause:
with alpha as (
select 1 as id
from dual
),
beta as (
select 1 as alpha_id,
1 as beta_no
from dual
union all
select 1 as alpha_id,
2 as beta_no
from dual
)
select a.id,
b.beta_no,
level as the_level
from alpha a
inner join beta b
on b.alpha_id = a.id
connect by level <= 4
AND PRIOR a.id = a.id
AND PRIOR b.beta_no = b.beta_no
AND PRIOR sys_guid() IS NOT NULL
order by a.id,
b.beta_no,
LEVEL;
ID BETA_NO THE_LEVEL
---------- ---------- ----------
1 1 1
1 1 2
1 1 3
1 1 4
1 2 1
1 2 2
1 2 3
1 2 4
An alternative would be to use the recursive with clause:
with alpha as (
select 1 as id
from dual
),
beta as (
select 1 as alpha_id,
1 as beta_no
from dual
union all
select 1 as alpha_id,
2 as beta_no
from dual
),
multiply (id, beta_no, rn) AS (SELECT a.id,
b.beta_no,
1 rn
FROM alpha a
INNER JOIN beta b
ON a.id = b.alpha_id
UNION ALL
SELECT ID,
beta_no,
rn + 1
FROM multiply
WHERE rn + 1 <= 4)
SELECT ID,
beta_no,
rn AS the_level
FROM multiply
order by id,
beta_no,
rn;
ID BETA_NO THE_LEVEL
---------- ---------- ----------
1 1 1
1 1 2
1 1 3
1 1 4
1 2 1
1 2 2
1 2 3
1 2 4

Get Hierarchy level and all node references on Oracle

I have been reading about CONNECT BY and CTE in Oracle, but I can't come up with a solution. I don't know how to use properly CONNECT BY to my needs, and recursive CTE's in Oracle are limited to 2 branches(one UNION ALL) and I'm using 3 branches.
In SQL Server it was kind of easy after I found this article. I only added another UNION ALL regarding to return all node references.
What I trying to do is having a hierarchy like this:
Code|Father
1 |NULL
2 |1
3 |2
And this should return me:
Node|Father|Level|JumpsToFather
1 |1 |1 |0
2 |1 |2 |1
2 |2 |2 |0
3 |1 |3 |2
3 |2 |3 |1
3 |3 |3 |0
Note: Yes I need to return a reference to themselves counting as zero jumps on the hierarchy
Here is a solution using a recursive CTE. I used lvl as column header since level is a reserved word in Oracle. You will see other differences in terminology as well. I use "parent" for the immediately higher level and "ancestor" for >= 0 steps (to accommodate your requirement of showing a node as its own ancestor). I used an ORDER BY clause to cause the output to match yours; you may or may not need the rows ordered.
Your question stimulated me to read again, in more detail, about hierarchical queries, to see if this can be done with them instead of recursive CTEs. Actually I already know you can, by using CONNECT_BY_PATH, but using a substr on that just to retrieve the top level in a hierarchical path is not satisfying at all, there must be a better way. (If that was the only way to do it with hierarchical queries, I would definitely go the recursive CTE route if it was available). I will add the hierarchical query solution here, if I can find a good one.
with h ( node, parent ) as (
select 1 , null from dual union all
select 2 , 1 from dual union all
select 3 , 2 from dual
),
r ( node , ancestor, steps ) as (
select node , node , 0
from h
union all
select r.node, h.parent, steps + 1
from h join r
on h.node = r.ancestor
)
select node, ancestor,
1+ (max(steps) over (partition by node)) as lvl, steps
from r
where ancestor is not null
order by lvl, steps desc;
NODE ANCESTOR LVL STEPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
Added: Hierarchical query solution
OK - found it. Please test both solutions to see which performs better; from tests on a different setup, recursive CTE was quite a bit faster than hierarchical query, but that may depend on the specific situation. ALSO: recursive CTE works only in Oracle 11.2 and above; the hierarchical solution works with older versions.
I added a bit more test data to match Anatoliy's.
with h ( node, parent ) as (
select 1 , null from dual union all
select 2 , 1 from dual union all
select 3 , 2 from dual union all
select 4 , 2 from dual union all
select 5 , 4 from dual
)
select node,
connect_by_root node as ancestor,
max(level) over (partition by node) as lvl,
level - 1 as steps
from h
connect by parent = prior node
order by node, ancestor;
NODE ANCESTOR LVL STEPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
4 1 3 2
4 2 3 1
4 4 3 0
5 1 4 3
5 2 4 2
5 4 4 1
5 5 4 0
thx for question, i spent 1 hour to write this:
with t as ( select code, parent, level l
from (select 1 as code, NULL as parent from dual union
select 2 , 1 from dual union
select 3 , 2 from dual
-- add some more data for demo case
union
select 4 , 2 from dual union
select 5 , 4 from dual
)
start with parent is null
connect by prior code = parent )
select code, (select code
from t t1
where l = ll
and rownum = 1
start with t1.code = main_t.code
connect by prior t1.parent = t1.code
) parent,
l code_level,
jumps
from (
select distinct t.*, l-level jumps, level ll
from t
connect by level <= l
) main_t
order by code, parent
as you can see, i'am add some more data to test my sql, here is output
CODE PARENT CODE_LEVEL JUMPS
---------- ---------- ---------- ----------
1 1 1 0
2 1 2 1
2 2 2 0
3 1 3 2
3 2 3 1
3 3 3 0
4 1 3 2
4 2 3 1
4 4 3 0
5 1 4 3
5 2 4 2
5 4 4 1
5 5 4 0
13 rows selected

How does pandas merge really sort its result when using its default, sort=False?

I'm a bit confused how the default sort works when I run a merge/join with 2 pandas dataframes. I would expect the order of my result set from
A.merge(B, how='left', on=[Col1, Col2])
to be how A was previously sorted, but in my experience, the ordering is slightly off - and by the keys of A. I find that the order of A maintains, except when keys are duplicated, the result set is ordered by those keys. Below is a crude example of what I have been seeing.
A is:
Col1 Col2 Col3
1 4 5 6
2 6 6 8
3 2 4 5
4 4 5 3
B is:
Col1 Col2 Col4
1 6 6 0
2 2 4 5
3 4 5 7
A.merge(B, how='left', on=[Col1, Col2])
Col1 Col2 Col3 Col4
1 4 5 6 7
2 4 5 3 7
3 6 6 8 0
4 2 4 5 5

Resources