如何将此子查询转换为联接?

时间:2018-11-27 13:49:44

标签: mysql sql join subquery

我有以下查询,该查询可以正常运行:

SELECT insent.id, notifications.id
FROM insent
WHERE insent.id IN (
    SELECT insent_id
    FROM notifications
);

这按预期工作,但我想将其转换为带有联接的查询。我可以这样做:

SELECT 
    insent.id, 
    notifications.id 
FROM insent 
JOIN notifications ON notifications.insent_id = insent.id

但是由于每条未发送的记录可以存在多个通知记录,因此与第一个查询/子查询组合相比,这将产生更多的结果。

有什么主意,如果存在多个通知记录,我怎么只显示一次发送的记录?

4 个答案:

答案 0 :(得分:2)

只需使用distinct即可避免insent重复

SELECT distinct
    insent.id
FROM insent 
JOIN notifications ON notifications.insent_id = insent.id

我相信使用IN的解决方案要好得多。查询优化器将更可能使用半联接。

SELECT insent.id
FROM insent
WHERE insent.id IN (
    SELECT insent_id
    FROM notifications
)

但是,不清楚您在问题中提供的第一个查询如何工作?您无法从外部查询访问嵌套在IN构造子查询中的属性。

答案 1 :(得分:1)

SELECT 
    insent.id, 
    notifications.id 
FROM insent 
JOIN (select distinct id, insent_id from notifications)notifications ON notifications.insent_id = insent.id

答案 2 :(得分:0)

用于Smarties的SQL的作者Joe Celko建议您正因如此使用IN谓词。您不想使用SELECT DISTINCT,因为它使用内部游标来减慢较大数据集上的内容并导致不良设计。您实际上是在试图通过另一个表中存在的标识符来限制插入结果。使用IN谓词的第一个查询是更好的查询。

答案 3 :(得分:0)

您可以尝试使用ROW_NUMBER

SELECT r.NotificationId,InsentId
FROM ( SELECT 
    insent.id AS InsentId, 
    notifications.id AS NotificationId,
    ROW_NUMBER () OVER ( PARTITION BY  i.id ORDER BY i.Id ) AS rn
FROM insent i
JOIN notifications n ON n.insent_id = i.id ) as r
WHERE rn=1