在此SQL查询中简化/重用子查询

时间:2017-04-04 02:02:03

标签: sql postgresql

我有以下SQL查询:

SELECT "users".* FROM "users"
WHERE (
  users.id IN (SELECT manager_id FROM managerships WHERE managerships.employee_id = 1234) OR
  users.custom_id IN (SELECT manager_custom_id FROM managerships WHERE managerships.employee_id = 1234) OR
  users.saml_id IN (SELECT manager_saml_id FROM managerships WHERE managerships.employee_id = 1234) OR
  users.email IN (SELECT manager_email FROM managerships WHERE managerships.employee_id = 1234)
)

现在我相信应该有一种方法可以从我的managerships表中选择一次并重复使用它,例如:

SELECT manager_id, manager_email, manager_custom_id, manager_saml_id FROM managerships WHERE managerships.employee_id = 1234

我怎样才能实现这一目标?谢谢!

3 个答案:

答案 0 :(得分:3)

您可以使用WITH将聚合带入CTE(公用表表达式):

WITH m AS (SELECT manager_id
                 ,manager_email
                 ,manager_custom_id
                 ,manager_saml_id 
           FROM   managerships 
           WHERE  managerships.employee_id = 1234
)
SELECT "users".* FROM "users"
WHERE (
  users.id IN (SELECT manager_id FROM m) OR
  users.custom_id IN (SELECT manager_custom_id FROM m) OR
  users.saml_id IN (SELECT manager_saml_id FROM m) OR
  users.email IN (SELECT manager_email FROM m)
);

请参阅https://www.postgresql.org/docs/9.1/static/queries-with.html

答案 1 :(得分:2)

您可以尝试一起加入usersmanagerships表:

SELECT t1.*
FROM "users" t1
INNER JOIN managerships t2
    ON t1.id        = t2.manager_id OR
       t1.custom_id = t2.manager_custom_id OR
       t1.saml_id   = t2.manager_saml_id OR
       t1.email     = t2.manager_email
WHERE t2.employee_id = 1234;

这种方法除了易于阅读之外,还具有可以在两个表上使用索引的优点,假设您已经定义了它们。

答案 2 :(得分:1)

您可以像这样编写查询:

SELECT u.*
FROM users u CROSS JOIN
     managerships m
WHERE m.employee_id = 1234 AND
      (u.id = m.manager_id OR
       u.custom_id = m.manager_custom_id OR
       u.saml_id = m.manager_saml_id OR
       u.email = m.manager_email 
      );

我认为性能没有任何改善。此查询的任何版本都需要managerships(employee_id)上的索引。使用此索引,您的查询和这应该具有几乎相同的性能。

注意:您可以使用on来表达这一点 - 它也会做同样的事情。由于OR条件无法真正优化,这就是我将它们放入WHERE子句的原因。