2017-04-04 48 views
0

我有以下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 

我該如何做到這一點?謝謝!

回答

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; 

這種做法,除了是更易於閱讀,還增加的優勢可能能夠在兩個表使用索引,假設你已經定義了它們。

+0

謝謝你,蒂姆!我採取了你的方法,它效果很好。我只需要對結果進行「分組」即可獲得唯一的條目。 –

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條款。

+0

謝謝,戈登! –

2

您可以使用採取聚集了成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

+0

不錯的做法,謝謝! –