Get a Group ID from Bridge table - sql

I'm trying to get a Group ID key from a bridge table that looks something like this:
GROUP_KEY DIM_KEY
1 11
1 12
1 13
1 14
2 11
2 12
3 11
3 12
3 13
3 15
4 11
5 11
5 12
5 13
I've searched a little bit a got this query:
SELECT b1.group_key
FROM BRIDGE b1
JOIN BRIDGE b2 ON (b1.group_key= b2.group_key)
JOIN BRIDGE b3 ON (b1.group_key= b3.group_key)
WHERE b1.dim_key = 11
AND b2.dim_key = 12
AND b3.dim_key = 13;
But this gets me 1,3 and 5, and I only want the 5, I can filter it further with a a count = 3, but my question is, is there a better way ? I'm using PL/SQL btw.

EDIT
if you are using Oracle 11g, try the following
SELECT group_key FROM (
SELECT GROUP_KEY, listagg(DIM_KEY, ',') WITHIN GROUP(ORDER BY DIM_KEY) DIM_KEY
FROM t
GROUP BY GROUP_KEY) WHERE dim_key = '11,12,13'

I donĀ“t really know what you want. But if you want to the count to be 3. Then you can do it like this:
WITH CTE
(
SELECT
COUNT(GROUP_KEY) OVER(PARTITION BY GROUP_KEY) AS Counts,
BRIDGE.*
FROM
BRIDGE
)
SELECT
*
FROM
CTE
WHERE
CTE.Counts=3
AND CTE.dim_key IN(11,12,13);

Related

How to update table with concatenation

I have table like this
create table aaa (id int not null, data varchar(50), numb int);
with data like this
begin
for i in 1..30 loop
insert into aaa
values (i, dbms_random.string('L',1),dbms_random.value(0,10));
end loop;
end;
now im making this
select a.id, a.data, a.numb,
count(*) over (partition by a.numb order by a.data) count,
b.id, b.data,b.numb
from aaa a, aaa b
where a.numb=b.numb
and a.data!=b.data
order by a.data;
and i want to update every row where those numbers are the same but with different letters, and in result i want to have new data with more than one letter (for example in data column- "a c d e"), i just want to create concatenation within. How can i make that? the point is to make something like group by for number but for that grouped column i would like to put additional value.
that is how it looks like in begining
id | data |numb
1 q 1
2 z 8
3 i 7
4 a 2
5 q 4
6 h 1
7 b 9
8 u 9
9 s 4
That i would like to get at end
id | data |numb
1 q h 1
2 z 8
3 i 7
4 a 2
5 q s 4
7 b u 9
Try this
SELECT MIN(id),
LISTAGG(data,' ') WITHIN GROUP(
ORDER BY data
) data,
numb
FROM aaa GROUP BY numb
ORDER BY 1
Demo
This selects 10 random strings 1 to 4 letters long, letters in words may repeat:
select level, dbms_random.string('l', dbms_random.value(1, 4))
from dual connect by level <= 10
This selects 1 to 10 random strings 1 to 26 letters long, letters do not repeat and are sorted:
with aaa(id, data, numb) as (
select level, dbms_random.string('L', 1),
round(dbms_random.value(0, 10))
from dual connect by level <= 30)
select numb, listagg(data) within group (order by data) list
from (select distinct data, numb from aaa)
group by numb

Get all of child nodes in a hierarchical data in SQL

I have the following sql table:
id parent_id
1 null
2 1
3 4
4 8
5 1
6 2
7 6
8 null
How can i get all of child nodes of some specific node?
For example with id = 1:
1 2 5 6 7
with id = 8
8 4 2
I've figured out in another blog, hope it will help other people:
with RECURSIVE cte(id,parent_id) as (
select
id,
parent_id
from forum
where id = 2
UNION ALL
select
forum.id,
forum.parent_id
from forum
inner join cte on forum.parent_id = cte.id
)
select * from cte

SQL Server column Sorting with 2 or more columns being sorted

I have these records in my table:
id sequence question answer letter
1 1 1 + 1 2 B
2 2 2 + 2 4 E
3 3 4 + 4 8 A
4 4 8 + 8 16 D
5 5 16 + 16 32 C
Is there any possibilites to make my table look like this? :
id sequence question answer letter
1 1 1 + 1 8 A
2 2 2 + 2 2 B
3 3 4 + 4 32 C
4 4 8 + 8 16 D
5 5 16 + 16 4 E
I mean the first one is i order by sequence, but i also wanted to get the order of it in letters because if not they will be in same position as therefore the question can be answered easily, I wanted the answer to come with the letter and order by it alphabetically. Please badly need your help :(
--DDL
CREATE TABLE test(id int,sequence int,question varchar(20),answer int, letter varchar(5) );
INSERT INTO test VALUES(1,1,'1+1',2,'B');
INSERT INTO test VALUES(2,2,'2+2',4,'E');
INSERT INTO test VALUES(3,3,'4+4',8,'A');
INSERT INTO test VALUES(4,4,'8+8',16,'D');
INSERT INTO test VALUES(5,5,'16+16',32,'C');
--SQL
SELECT A.id,
A.sequence,
A.question,
B.answer,
B.letter
FROM
(
SELECT id,
sequence,
question,
ROW_NUMBER() OVER ( ORDER BY id ) AS rn
FROM test
) A
INNER JOIN
(
SELECT answer,
letter,
ROW_NUMBER() OVER ( ORDER BY letter ) AS rn
FROM test
) B
ON A.rn = B.rn;
SQL Fiddle :-
http://sqlfiddle.com/#!6/96e09/3

Extracting sub data from a table

I would be happy for your help.
I have a table like this :
[MS_CODE] [MS_SML]
1 43
1 AA
2 51
3 24
3 21
4 11
4 43
5 AA
6 11
I want to write a query that will serach for the [MS_SML] which shows up in group (1 or 2 or 3) And (4 or 5 or 6) in [MS_Code].
For example:
43,AA because 43 is in a row where ms_code is 1 and 4 and same for 'AA'. I would like to create output like this:
[MS_Code] [MS_SML]
1 43
4 43
1 AA
5 AA
Thank you very much for your help!
One method is to use exists and apply your criteria:
select t.*
from t
where exists (select 1
from t t2
where t2.ms_sml = t1.ms_sml and t2.ms_code in (1, 2, 3)
) and
exists (select 1
from t t2
where t2.ms_sml = t1.ms_sml and t2.ms_code in (4, 5, 6)
);
Here is one way to do it.
select ms_code, ms_sml
from msc
where ms_sml in
(
select ms_sml
from msc
where ms_code in (1,2,3)
intersect
select ms_sml
from msc
where ms_code in (4,5,6)
)
order by ms_sml, ms_code
Note: If there is more than one ms_code for a given ms_sml in the same group, this will return all of them.
Suppose AA is mapped to 1, 3 and 5, this will return
1 AA
3 AA
5 AA
If that is an issue, We may need additional logic to deal with that: for example pick the minimum value of ms_code within the group.

Updating column based on another column's value

How do i update table structured like this:
id[pkey] | parent_id | position
1 1
2 1
3 1
4 1
5 1
6 2
7 2
8 2
9 2
10 3
11 3
12 3
...and so on
to achieve this result:
id[pkey] | parent_id | position
1 1 1
2 1 2
3 1 3
4 1 4
5 1 5
6 2 1
7 2 2
8 2 3
9 2 4
10 3 1
11 3 2
12 3 3
...and so on
I was thinking about somehow mixing
SELECT DISTINCT parent_id FROM cats AS t;
with
CREATE SEQUENCE dpos;
UPDATE cats t1 SET position = nextval('dpos') WHERE t.parent_id = t1.parent_id;
DROP SEQUENCE dpos;
although im not really experienced with postgres, and not sure how to use some kind of FOREACH. I appreciate any help
You can get the incremental number using row_number(). The question is how to assign it to a particular row. Here is one method using a join:
update cats
set position = c2.newpos
from (select c2.*, c2.ctid as c_ctid,
row_number() over (partition by c2.parent_id order by NULL) as seqnum
from cats c2
) c2
where cats.parent_id = c2.parent_id and cats.ctid = c2.c_ctid;
Use row_number function
select parent_id,
row_number() over (partition by parent_id order by parent_id) as position_id from table
Try this:
UPDATE table_name set table_name.dataID = v_table_name.rn
FROM
(
SELECT row_number() over (partition by your_primaryKey order by your_primaryKey) AS rn, id
FROM table_name
) AS v_table_name
WHERE v_table_name.your_primaryKey = v_table_name.your_primaryKey;