我是Postgres的新手,我曾经使用过MySQL。
我的问题很简单,在MySQL中也不会发生。 t1
是我的主表,t2
包含t1
状态中t1
字段的更新历史记录。因此,只要t2
中的条目更改其状态字段,就会使用当前时间戳和新状态值将新记录添加到t1
。
现在我想获取SELECT
t1.id,
t1.message,
MAX(t2.creation_timestamp)
FROM table_1 t1
LEFT JOIN table_2 t2 ON t1.id = t2.table_1_id
WHERE t1.id = 1271
GROUP BY t1.id,t1.message
中特定条目的最新状态和时间戳,例如id 1271 。我可以通过以下查询获取最新的时间戳。
SELECT
t1.id,
t1.message,
t2.status,
MAX(t2.creation_timestamp)
FROM table_1 t1
LEFT JOIN table_2 t2 ON t1.id = t2.table_1_id
WHERE t1.id = 1271
GROUP BY t1.id,t1.message
但是当我尝试使用MAX时间戳获取该特定行的状态时。
ERROR: column "t2.status" must appear in the GROUP BY clause or be used in an aggregate function
我收到以下错误:
{{1}}
如何使用MAX时间戳获取记录的状态?
答案 0 :(得分:2)
您的查询被Postgres拒绝,因为它是无效的SQL。 MySQL中也存在这个问题,到目前为止你很幸运,因为MySQL选择返回随机值而不是拒绝无效组(你可能想要阅读this或this以获取有关MySQL的详细信息实现)
Postgres中最有效的解决方案是使用distinct on ()
SELECT distinct on (t1.id)
t1.id,
t1.message,
t2.status,
t2.creation_timestamp
FROM table_1 t1
LEFT JOIN table_2 t2 ON t1.id = t2.table_1_id
WHERE t1.id = 1271
ORDER BY t1.id, t2.creation_timestamp DESC;
但是,如果将 id
定义为table_1
的主键,并且两个表之间存在正确的外键关系,则Postgres 将接受部分组,因为它知道id
是唯一的。
psql (9.6.1)
Type "help" for help.
postgres=> create table table_1 (id integer primary key, message text);
CREATE TABLE
postgres=> create table table_2 (table_1_id integer references table_1, status text, creation_timestamp timestamp);
CREATE TABLE
postgres=> insert into table_1
postgres-> values
postgres-> (1271, 'one'),
postgres-> (1272, 'two'),
postgres-> (1273, 'three');
INSERT 0 3
postgres=> insert into table_2
postgres-> values
postgres-> (1271, 'active', timestamp '2016-12-30 10:00:00'),
postgres-> (1271, 'active', timestamp '2016-12-30 11:00:00'),
postgres-> (1271, 'active', timestamp '2016-12-30 12:00:00'),
postgres-> (1272, 'active', timestamp '2016-12-30 11:00:00'),
postgres-> (1272, 'active', timestamp '2016-12-30 12:00:00'),
postgres-> (1273, 'active', timestamp '2016-12-30 13:00:00'),
postgres-> (1273, 'active', timestamp '2016-12-30 13:00:00');
INSERT 0 7
postgres=> SELECT
postgres-> t1.id,
postgres-> t1.message,
postgres-> MAX(t2.creation_timestamp)
postgres-> FROM table_1 t1
postgres-> LEFT JOIN table_2 t2 ON t1.id = t2.table_1_id
postgres-> WHERE t1.id = 1271
postgres-> GROUP BY t1.id
postgres-> ;
id | message | max
------+---------+---------------------
1271 | one | 2016-12-30 12:00:00
(1 row)
SQLFiddle示例:http://sqlfiddle.com/#!15/7cfc8/1
答案 1 :(得分:1)
你应该拥有table_1的最新状态,你不应该从table_2中获取它,你只需要最新的时间戳
SELECT
t1.id,
t1.message,
t1.status,
tmax.creation_timestamp
from table_1 t1
left join (
select table_1_id, MAX(creation_timestamp) creation_timestamp
from table_2
group by table_1_id
) tmax on tmax.table_1_id = t1.id
WHERE t1.id = 1271
答案 2 :(得分:0)
使用子查询选择加入max(creation_timestamp)
SELECT
t1.id,
t1.message,
t2.status,
t2.creation_timestamp
FROM table_1 t1
LEFT JOIN table_2 t2 ON t1.id = t2.table_1_id
and t2.creation_timestamp = (SELECT MAX(creation_timestamp)
from table_2 t3 where t1.id = t3.table_1_id )
WHERE t1.id = 1271