代码之家  ›  专栏  ›  技术社区  ›  kramer65

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

  •  -2
  • kramer65  · 技术社区  · 6 年前

    我得到了以下查询,它按预期工作:

    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 回复  |  直到 6 年前
        1
  •  2
  •   Radim Bača    6 年前

    只是使用 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-construct子查询中的属性。

        2
  •  1
  •   Ravi Bharati Mathapati    6 年前
    SELECT 
        insent.id, 
        notifications.id 
    FROM insent 
    JOIN (select distinct id, insent_id from notifications)notifications ON notifications.insent_id = insent.id
    
        3
  •  0
  •   Paurian    6 年前

    Joe Celko是SQL for Smarties的作者,他建议您使用IN谓词就是为了这个原因。您不想使用SELECT DISTINCT,因为它使用了一个内部游标,这会减慢较大数据集上的速度,并促进糟糕的设计。您试图通过在另一个表中存在什么标识符来限制默认结果。使用IN谓词的第一个查询是更好的查询。

        4
  •  0
  •   Sanal Sunny    6 年前

    你可以试试 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