Postgres JOIN条件与WHERE条件


12

Postgres新手在这里。

我想知道此查询是否已优化?我尝试仅加入100%必需的值,并将所有动态条件保留在WHERE子句中。见下文。

SELECT *
    FROM
      myapp_employees
    JOIN myapp_users ON
      myapp_users.user_id=myapp_employees.user_id
    JOIN myapp_contacts_assoc ON
      myapp_contacts_assoc.user_id=myapp_users.user_id
    JOIN myapp_contacts ON
      myapp_contacts.contact_id=myapp_contacts_assoc.contact_id
    WHERE
      myapp_contacts.value='test@gmail.com' AND
      myapp_contacts.type=(1)::INT2 AND
      myapp_contacts.is_primary=(1)::INT2 AND
      myapp_contacts.expired_at IS NULL AND
      myapp_employees.status=(1)::INT2 AND
      myapp_users.status=(1)::INT2
    LIMIT 1;

注意:对于上下文,此proc正在检查用户是否也是雇员(特权/不同用户类型)。

无论如何,这是正确的方法吗?例如,JOIN ON是否应该包含更多的语句,例如检查是否为expired_at IS NULL?为什么或为什么这没有道理?


那您的Postgres版本呢?(SELECT version();
Erwin Brandstetter,2016年

@ErwinBrandstetter我正在运行PostgreSQL 9.3.14。这是我在每个功能中都需要的东西吗?

2
不,我们在dba.SE上要求您声明相关的软件版本,因为它们在许多问题上会有所不同。
Erwin Brandstetter,2016年

Answers:


14

从逻辑上讲,无论您将条件放在an的join子句INNER JOIN还是WHERE同一个子句中,都没有任何区别SELECT。效果是一样的。

(并非如此OUTER JOIN!)

使用默认设置进行操作时,它对查询计划或性能也没有影响。只要表的数量不大于(默认值),Postgres可以自由地重新安排联接和JOINWHERE条件以寻求最佳查询计划。细节:join_collapse_limit8

为了提高可读性和可维护性,在各个JOIN子句中放置连接表的条件以及在WHERE子句中放置一般条件是有意义的。

您的查询看起来还不错。不过,我会使用表别名来减少噪音。

小细节:

int2 '1'甚至1::int2(1)::INT2。而且,在与定义明确的数值数据类型的值进行比较时,纯数值常量1也足够好。


2

几点。

  1. 如果您要以相同的名称(user_id)加入某个条件,则可以使用USING (user_id)而不是ON (a.user_id = b.user_id)。这也可以避免多余的列可能被输出(如果您正在SELECT *生产中运行)。

  2. 1::int2有问题。无论是statusis_primary等人都已经int2在这种情况下,文本1将被自动强制转换为INT2,或INT2为pg认为合适的铸造为int。或者,如果您将它们存储为常规int,然后将其强制转换,就好像在计算中产生了不同-并非如此,仅强制转换会导致失败。

  3. 如果可能,所有:: int2应该都应存储为boolean。然后,您也可以将WHERE条件写得更简单。

  4. 对于您的类型和状态,可能需要一种ENUM类型。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.