I need to transform this:
PositionID
ReportsToID
A
B
A
C
B
D
C
E
D
Into this:
PositionID
ReportsToID
Level 1 ID
Level 2 ID
Level 3 ID
Level 4 ID
Level 5 ID
A
A
B
A
A
B
C
B
A
B
C
D
C
A
B
C
D
E
D
A
B
C
D
E
I am a complete SQL novice and no idea how to tackle this... Any help would be greatly appreciated!
Googling for code that has done this already - have not found any
I decided to write a generic solution for unlimited levels. It's possible to walk all the levels using a recursive CTE.
For example:
with recursive
n as (
select position_id, reports_to_id, reports_to_id as rti,
cast(position_id as varchar) as pt
from t
union all
select n.position_id, n.reports_to_id, t.reports_to_id,
t.position_id || ' < ' || n.pt
from n
join t on n.rti = t.position_id
)
select position_id, reports_to_id, pt from n where rti is null
Result:
position_id reports_to_id pt
------------ -------------- -----------------
A null A
B A A < B
C B A < B < C
D C A < B < C < D
E D A < B < C < D < E
See running example at db<>fiddle.
If you need a static solution with a specific number of columns, it can be done with multiple unioned-queries, each one with an increasing number of joins.
Related
SQL Server 2008
Table A looks like:
A_ID v1 v2 v3
---------------------------
1 d e f
1 a b c
1 a b d
2 d a b
2 e f g
3 d e f
3 e f g
3 d a b
and Table B is similar:
B_ID v1 v2 v3
---------------------------
Q a b c
Q b a c
Q a b d
R d e f
R a b c
R d e f
P e f g
P d a b
What I need back from these two tables are the (A_ID, B_ID) pairs, if any, where each row of Table B where B_ID = any one value has one matching row in Table A where A_ID = any one value. In other words, I need to the complete matching set in A for each full set of triples in B--no super sets or subsets. The value of B_ID and A_ID is immaterial.
I thought partitioning would be the way to go, since I already have the column that naturally partitions A and B, and I also thought I could pre-select which paritions where JOINed by ensuring only partitions with matching numbers of rows would be attempting. I haven't been able to do either--partitioning both tables was easy, but I see no way to tell the join to only act on the partitions.
In this example, (2,P) would be returned because all rows in Set P match all rows in Set 2. Result (1, R) would NOT be returned because all rows of Set R are not matched by all rows of Set 1, etc.
Using symetric difference:
SELECT DISTINCT a1.A_ID, b1.B_ID
FROM A a1,B b1
WHERE NOT EXISTS (
(SELECT v1,v2,v3
FROM A WHERE A.A_ID = a1.A_ID
EXCEPT
SELECT v1,v2,v3
FROM B WHERE B.B_ID = b1.B_ID
)
UNION ALL
(
SELECT v1,v2,v3
FROM B WHERE B.B_ID = b1.B_ID
EXCEPT
SELECT v1,v2,v3
FROM A WHERE A.A_ID = a1.A_ID)
);
LiveDemo
Given I have columns A B C D ….. Z
I want to Group-By on A, B , C Having Count(*) > 1 and then for each of those rows, I want to SELECT the rest of the Columns as well that were not included in the aggregate.
The result would be like
Occurrences A B C D E F G ------- Z
3 e e k q r y e ------- j
3 e e k f t d t ------- y
3 e e k w e q c ------- d
2 f r s w e q c ------- d
2 f r s w e q c ------- d
How can I do that?
You don't want GROUP BY, you want ORDER BY. To get the first column, you can use window functions, which are ANSI standard and supported by most databases:
select t.*
from (select count(*) over (partition by a, b, c) as occurrences,
t.*
from t
order by a, b, c
) t
where occurrences > 1;
I'm building matching rules for data reconciliation systems and need your advise on adjusting my sql for it as it currently doesn't return what I need.
There are 2 source tables:
Table X Table Y
--------------------- ----------------------
Exec_ID From To Exec_ID From To
1 A B 1 B C
2 A B 2 B C
3 A B 3 B C
4 A B
5 B C
Matching conditions are:
X.To = Y.From
X.Exec_ID = Y.Exec_ID
if there is A -> B and then B -> C, it should return A -> C in the end.
if there is only A -> B and no further B -> C, it should return A -> B.
So the output should be the following.
From To
---------
A C
A C
A C
A B
SQL I'm using is:
select X.From, Y.To
from x
left outer join y on
x.To = Y.From
and x.Exec_ID = y.Exec_ID
It returns the values like
A C
A C
A C
A Null
So the last record is incorrect as it should be A B. Please help to adjust.
Check for null?
select X.From, [To] = COALESCE(Y.To, X.To)
from x
left outer join y on
x.To = Y.From
and x.Exec_ID = y.Exec_ID
Consider the following table in Oracle
sortOrder thisID levelNo
------------------- ------------------- ---------------------
1 A 0
2 B 1
3 C 1
4 D 2
5 E 3
6 F 3
7 G 1
8 H 0
9 I 1
Which could be seen visually as
A
B
C
D
E
F
G
H
I
How could I determine the child parent relationship, to output the following below? The relationship is based on the sortOrder and levelNo.
thisID parentID
------------------- ---------------------
A A
B A
C A
D C
E D
F D
G A
H H
I H
I am familiar with using queries to determine the level based on a hierarchical parent-child relationship, but haven't figured out a way to do it in reverse.
Please try
SELECT
T.thisID
, CASE T.levelNo
WHEN 0
THEN T.thisID
ELSE (
SELECT thisID FROM Table1
WHERE sortOrder = (
SELECT MAX(sortOrder) FROM Table1
WHERE (levelNo = T.levelNo - 1)
AND sortOrder < T.sortOrder
)
)
END parent
FROM Table1 T
ORDER BY sortOrder;
See it in action: SQL Fiddle.
Please comment if and as further detail / adjustment is required.
my table looks like:
column 1 | column 2
--------------------
A L
B M
C N
D O
E P
F Q
G R
H S
I T
J U
K V
Now I want to "concatenate" fractions of n-rows (n is variable) together.
For example:
-) if n = 4, the output should be:
column 1 | column 2 | column 1 | column 2 | column 1 | column 2
A L E P I T
B M F Q J U
C N G R K V
D O H S
-) if n = 10, the output should be:
column 1 | column 2 | column 1 | column 2
A L K V
B M
C N
D O
E P
F Q
G R
H S
I T
J U
I thought about using a temp table and a loop. After every iteration, I select fractions of n-rows and concatenate them together (with union). However, I think this solution could be a little slow for large datasets.
Maybe someone of you knows a better approach?
I would really appreciate if someone could help me with this.
Kind Regards
Bernhard
this is not complete
pivot is left,i was thinking of doing something like this,
Declare #n int=4
Declare #j int
Declare #k int
Select #j=count(*) from #t
if(#j%#n=0)
set #k= (#j/#n)
else
set #k= (#j/#n)+1
--select #k
;with CTE as
(
select *,ntile(#k)over(order by column1)rn from #t
)
select * from cte