编写此SQL比使用WHERE ... IN(子查询)有更好的方法吗?

时间:2010-02-05 20:29:33

标签: sql performance optimization subquery in-subquery

有没有比使用WHERE ... IN(子查询)编写此SQL更好的方法?

  SELECT device.mac, reseller.name, agent.name
  FROM device
  LEFT JOIN global_user
    ON device.global_user_id = global_user.id
  LEFT JOIN agent
    ON global_user.id = agent.global_user_id
  LEFT JOIN reseller
    ON global_user.id = reseller.global_user_id
        OR agent.reseller_id = reseller.id
  WHERE device.global_user_id IN (
    SELECT global_user_id
        FROM reseller
        WHERE id = '200'
  ) OR device.global_user_id IN (
    SELECT global_user_id
        FROM agent
        WHERE reseller_id = '200'
  );

我试图在特定的经销商处获取所有设备的列表,以及一些经销商/代理商详细信息。这将包括直接分配给经销商的设备和分配给经销商下的代理商的设备。 reseller.id是独一无二的。它将在postgresql数据库上执行。

设备分配给代理和代理商。代理商被分配给经销商。

这个查询有效,但我没有经常在JOIN中使用OR,我通常会尝试避免使用子查询。这个查询概念会经常使用,所以我想确保我没有忽略某些东西。

感谢您的任何反馈。

3 个答案:

答案 0 :(得分:3)

你可以给它一个旋转:

 SELECT device.mac, reseller.name, agent.name
  FROM device
  JOIN
  (
      SELECT global_user_id
      FROM reseller
      WHERE id = '200'
      UNION
      SELECT global_user_id
      FROM agent
      WHERE reseller_id = '200'
  ) r ON device.global_user_id = r.global_user_id
  LEFT JOIN global_user
    ON device.global_user_id = global_user.id
  LEFT JOIN agent
    ON global_user.id = agent.global_user_id
  LEFT JOIN reseller
    ON global_user.id = reseller.global_user_id
        OR agent.reseller_id = reseller.id

<强>澄清: 尝试查询的不同变体以确保最终获得性能最佳的查询总是一个好主意(尽管通常,不同的变体会导致查询优化器生成相同的执行计划)。从SQL Server的角度来看,处理查询的顺序意味着在WHERE子句之前首先处理JOIN。所以从理论上讲,这种JOIN方法应该先缩减结果集。

答案 1 :(得分:1)

这个怎么样?

SELECT d.mac, r.name, a.name
FROM device as d, global_user as g, agent as a, reseller as r
WHERE d.global_user_id = g.id
  AND g.id = a.global_user_id
  AND (g.id = r.global_user_id OR a.reseller_id = r.id)
  AND (r.id = '200' OR a.reseller_id = '200');

答案 2 :(得分:1)

如果很容易替换它们,我会尽量避免使用子查询和IN子句。如果我理解正确DB model,则此查询应产生相同的结果:

SELECT      DISTINCT
            device.mac, reseller.name, agent.name
FROM        device
LEFT JOIN   global_user
        ON  device.global_user_id = global_user.id
LEFT JOIN   agent
        ON  global_user.id = agent.global_user_id
LEFT JOIN   reseller
        ON  global_user.id = reseller.global_user_id
        OR  agent.reseller_id = reseller.id
WHERE       reseller.id = '200'
        OR  agent.reseller_id = '200'