可以在Postgres中有效地LEFT OUTER JOIN左表行的子集吗?

时间:2012-02-02 22:08:17

标签: sql performance postgresql join

假设我有以下表格:

table_1                  table_2
id_a    name             id_a    id_b
1       c                1       1
2       a                1       2
3       b                2       1
                         2       2

现在考虑以下LEFT OUTER JOIN:

SELECT *
FROM table_1
LEFT OUTER JOIN table_2 USING (id_a)

id_a    name  id_b  
1       c     1
1       c     2
2       a     1
2       a     2
3       b

现在想象'FROM table_1'实际上是一个复杂的子查询,如:

SELECT * FROM huge_table WHERE expensive_conditions_producing_three_rows

是否可以编写仅以最小名称连接左行的查询,而无需完全重新运行子查询?您可以假设您对子查询有一定的控制权,即您可以根据需要添加ORDER BY。

换句话说,最终结果应如下所示:

id_a    name  id_b
1       c
2       a     1
2       a     2
3       b

我考虑使用SELECT INTO将子查询结果放在临时表中。那么计算JOIN ON条件下使用的最小值不会有问题。但我宁愿避免这种情况,除非它是唯一的解决方案。

编辑:我会等待几天,然后接受最佳解决方案,无论PG版本如何。但是,非常感谢PG 8.3及更早版本中的一个。

2 个答案:

答案 0 :(得分:5)

使用Window functions(可从PostgreSQL 8.4获得):

SELECT *
FROM
      ( SELECT *
             , ROW_NUMBER() OVER (ORDER BY SomeColumn) AS RowNum
        FROM table_1
      ) AS a
  LEFT JOIN
      table_2 AS b
    ON 
       (join condition)
    AND
       a.RowNum = 1

答案 1 :(得分:3)

使用CTE (common table expression)(适用于PostgreSQL 8.4或更高版本):

WITH cte AS (
    SELECT id_a, name
    FROM   table_1
    WHERE  expensive_conditions_producing_three_rows
    )
SELECT c.id_a, c.name, t2.id_b
FROM   cte c
LEFT   JOIN table2 t2 ON t2.id_a = c.id_a
                     AND t2.name = (SELECT min(name) FROM cte)