在表连接中使用聚合函数的最有效方法是什么?

时间:2017-07-24 18:37:13

标签: postgresql left-join aggregate-functions

我正在尝试连接两个表,其中表1中的所有记录都具有唯一ID,表2 可以包含表1中id的多个记录(表1中的ID可能没有任何记录)表2中的相应记录。)

我想加入表二中的最新记录。

SELECT id, MAX(date) AS DATE FROM table_two

Above返回特定id的最新记录。

SELECT * FROM table_one t1 LEFT JOIN table_two t2 ON t1.id = t2.id

Above返回连接表,但也返回重复项。

如何构建join语句以仅返回表2中的最新记录?

这样的事情:

SELECT * FROM table_one t1 LEFT JOIN table_two t2 ON t1.id = t2.id, MAX(t2.date) AS date GROUP BY date 

上方返回错误:ERROR: aggregate functions are not allowed in functions in FROM

我知道我可以使用子查询来获取最新记录但不确定最有效的方法。

2 个答案:

答案 0 :(得分:2)

您必须使用子查询。 以下是两个可能的答案:

使用row_number和子查询

select * from(
    SELECT t1.*,row_number() over(partition by t2.id order by t2.date desc) as row_num
    FROM table_one t1
    LEFT JOIN table_two t2 ON t1.id = t2.id
)t
where t.row_num = 1

使用max和子查询

SELECT * FROM table_one t1 
LEFT JOIN 
(
    SELECT id, MAX(date) AS DATE FROM table_two group by id
)t2
ON t1.id = t2.id

答案 1 :(得分:1)

这两项都未经过测试;如果设置了rextester.com测试用例,我会得到它。

Postgresql 9.2?我认为,使用lateral关键字实现外部应用。这基本上针对表1运行select,然后对表1中的每个记录运行表2中的select;从表2返回相应身份证的最新日期记录;但是不必在循环中这样做,引擎可以某种方式将连接作为“SET”处理,因此不会受到循环/逐行性能影响。

SELECT * 
FROM table_one t1 
LEFT JOIN LATERAL (SELECT A.*
                   FROM table_two A
                   WHERE A.ID = T1.ID
                   ORDER BY A.Date desc
                   LIMIT 1) t2 
  ON TRUE

Grouped LIMIT in PostgreSQL: show the first N rows for each group?其他例子。

- 由于不使用分析函数或横向函数,因此应该可用于许多先前版本。

SELECT T1.*, t2.*
FROM table_one t1 
LEFT JOIN (SELECT A.* 
           FROM table_two A
           INNER JOIN (SELECT MAX(date) AS date, ID 
                       FROM table_two
                       GROUP BY ID) B
              on B.ID = A.ID
             and B.Date = A.Date) t2
 ON t1.id = t2.id 

上述基本概念...获取表2中记录的最大日期和ID 将此连接返回到table2的基本集,以获取table2中具有每个ID的最大日期的记录的所有详细信息。然后加入表1以获得t1和t2值。