Za7pi
Za7pi

Reputation: 1418

Get value of at least one coincidense between related tables postgres

I have 3 tables:

CREATE TABLE public.student (id serial NOT NULL PRIMARY KEY,"student" varchar(30) NOT NULL) WITH (OIDS = FALSE);

  CREATE TABLE public."class" (id serial NOT NULL PRIMARY KEY,"class" varchar(30) NOT NULL) WITH (OIDS = FALSE);



 CREATE TABLE public.student_class (student_id integer, class_id integer, /* Keys */ CONSTRAINT student_class_index01
    PRIMARY KEY (student_id, class_id)) WITH (OIDS = FALSE);

With these values:

INSERT INTO public.student_class ("student_id","class_id") VALUES(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(2,1),(2,2),(2,3),(3,4),(3,5),(3,6),(3,7),(3,8);

I want to now the names of the students that have at least one coincident class with other one:

Student 1 has got at least one coincidence with 2 and 3. Student 2 has got at least one coincidence with 1. Student 3 has got at least one coincidence with 1.

I have tried this, but it is not doing it by student.

SELECT distinct a.id,a.student from public.student a
LEFT OUTER JOIN public.student_class b ON b.student_id=a.id
LEFT OUTER JOIN public.class d ON d.id=b.class_id
WHERE class_id IN(select class_id from student_class where student_id not in(1))
AND a.id not in(1);

I think taht is easier than I think. Thanks.

Upvotes: 0

Views: 225

Answers (3)

Rémy  Baron
Rémy Baron

Reputation: 1399

What do you think about this :

with student_lst_classes as (
    select student_id,array_agg(class_id order by class_id) lst_classes
      from student_class  group by 1
 ) 
select st1.student,string_agg(st2.student,';' order by st2.student ASC) lst_student_coincident from 
 (student_lst_classes l1 join student st1 on (st1.id=l1.student_id)) 
 ,(student_lst_classes l2 join student st2 on (st2.id=l2.student_id))
where l1.student_id!=l2.student_id and l1.lst_classes && l2.lst_classes
group by 1 order by 1

Upvotes: 1

joop
joop

Reputation: 4503

Besically a cartesian join of student X student, so there are no duplicates to take care of. (except for the symmetry s1 <--> s2)

SELECT s1.id AS a_id, s1.student AS a_student
        , s2.id AS b_id, s2.student AS b_student
FROM student s1
JOIN student s2 ON EXISTS (
        SELECT *
        FROM student_class x1
        JOIN student_class x2 ON x2.class_id = x1.class_id
        WHERE x1.student_id = s1.id
        AND x2.student_id = s2.id
        )
WHERE s1.id < s2.id -- tie-breaker
        ;

Upvotes: 1

David Aldridge
David Aldridge

Reputation: 52356

Try this:

select *
from   student
where  exists (select null
                 from student_class sc1
                where sc1.student_id = student.id
                  and exists (select null
                                from student_class sc2
                               where sc2.class_id   =  sc1.class_id
                                 and sc2.student_id != sc1.student_id))

Upvotes: 1

Related Questions