如何避免跨三个连接表的SQL查询重复

Cha*_*ain 11 sql

当我在下面的示例中执行两个LEFT JOIN以获取"event_name"时,我得到了重复项.我用这种方式设置了112个案例.但是,如果我摆脱2 LEFT JOIN行并运行查询,我得到正确的100条记录,没有重复.我尝试使用下面的代码进行DISTINCT,但我仍然得到112重复.

SELECT "cases"."id", "cases"."date", "cases"."name", "event"."event_name" 
FROM "cases"
LEFT JOIN "middle_table" ON "cases"."serial" = "middle_table"."m_serial"
LEFT JOIN "event" ON "middle_table"."e_serial" = "event"."ev_serial"
WHERE "cases"."date" BETWEEN '2012-12-11' AND '2012-12-13'
Run Code Online (Sandbox Code Playgroud)

如何指定我只需要"案例"中的确切100个案例,并且我不希望连接中的表中的任何内容产生更多行?

谢谢!

And*_*eKR 8

您需要扩展ON子句以包含条件,以便对于每个条目,cases只有一个条目middle_table匹配条件,并且对于每个条目,middle_table只有一个条目event:

LEFT JOIN middle_table ON cases.serial = middle_table.m_serial AND some_condition
Run Code Online (Sandbox Code Playgroud)

你当然可以使用DISTINCT.如果不工作就意味着你的结果是在所有领域的不同cases.id,cases.date,cases.nameevent.event_name.检查结果并确定要丢弃的条目,并在ON子句中包含该条件.


Joh*_*van 7

问题是您在要加入的表格中有多个匹配项.您的代码有效地说:

select *
from parent
left outer join child on parent.id = child.parentId
Run Code Online (Sandbox Code Playgroud)

如果父母有两个孩子,你会得到两个孩子; 所以父母出现两次.

如果您只想在需要妥协时获得父母; 你不能有两个孩子.对子表中的列执行聚合函数,并对父表中的列执行分组,或者rownumber() over partition by (list,of,parent,columns order by list,of,child,columns) r在内部语句和where r=1外部语句中使用,如下所示:

select p.id, p.name, max(c.id), max(c.name) --nb: child id and name may come from different records
from parent p
left outer join child c on parent.id = child.parentId
group by p.id, p.name
Run Code Online (Sandbox Code Playgroud)

要么

select *
from 
(
    select p.id, p.name, c.id, c.name
    , rownumber() over (partition by p.id order by c.id desc) r
    from parent p
    left outer join child c on parent.id = child.parentId
) x
where x.r = 1
Run Code Online (Sandbox Code Playgroud)

UPDATE

如评论中所述,如果子数据完全相同,您可以这样做:

select p.id, p.name, c.name
from parent p
left outer join 
(
    select distinct c.parentId, c.name
    from child
) c on parent.id = child.parentId
Run Code Online (Sandbox Code Playgroud)

或者(如果有几个字段不同但你不在乎你得到了什么)

select p.id, p.name, c.id, c.name
from parent p
left outer join 
(
    select max(c.id) id, c.parentId, c.name
    from child
    group by c.parentId, c.name
) c on parent.id = child.parentId
Run Code Online (Sandbox Code Playgroud)