【问题标题】:Get value of at least one coincidense between related tables postgres获取相关表postgres之间至少一个重合的值
【发布时间】:2015-09-15 08:55:35
【问题描述】:

我有 3 张桌子:

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);

使用这些值:

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);

我现在想知道至少有一门与另一门重合的学生的姓名:

学生 1 与 2 和 3 至少有一次重合。学生 2 有 与 1 至少有一个巧合。学生 3 至少有一个巧合 与 1 重合。

我试过这个,但不是学生做的。

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);

我认为 taht 比我想象的要容易。谢谢。

【问题讨论】:

  • 所以你想要的是一个学生列表,在student_class中存在一条记录,在student_class中也存在另一条具有相同class_id但不同student_id的记录。所以嵌套的存在子句应该这样做。
  • 顺便说一句,您可能希望去掉表名和列名周围的双引号。糟糕的实践,这使得编写代码变得更加困难。
  • 另外,当您的结果集需要一个不同的,您应该始终考虑您的查询结构是否正确。在这种情况下,您应该能够编写查询而不需要 distinct。
  • 是的,你是对的。谢谢你的提示

标签: postgresql select join


【解决方案1】:

您对此有何看法:

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

【讨论】:

  • 就是这样。按 string_agg(st2.student,';') lst_student_coincident 排序呢?可能吗?我按 2 点了订单,但没有得到很好的排序。我的意思是: order asc= "Anne;Jamie" order desc "Jaime;Anne"
  • replace : [ select st1.student,string_agg(st2.student,';') lst_student_coincident from ..] by [ select st1.student,string_agg(st2.student,';' order by st2.student ASC) lst_student_coincident from ...]
【解决方案2】:

试试这个:

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))

【讨论】:

  • 不完全是。我想知道学生 2 的其他学生有哪些至少与她相同的课程
  • @Za7pi:您应该在问题中指定。
【解决方案3】:

基本上是 student X student 的笛卡尔连接,因此无需处理重复项。 (除了对称性 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
        ;

【讨论】:

    猜你喜欢
    • 2013-12-30
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    • 2013-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    相关资源
    最近更新 更多