【发布时间】:2011-06-07 15:44:34
【问题描述】:
我正在使用 Postgres,无法获取表的最后一条记录:
my_query = client.query("SELECT timestamp,value,card from my_table");
如果知道时间戳是记录的唯一标识符,我该怎么做?
【问题讨论】:
标签: sql postgresql
我正在使用 Postgres,无法获取表的最后一条记录:
my_query = client.query("SELECT timestamp,value,card from my_table");
如果知道时间戳是记录的唯一标识符,我该怎么做?
【问题讨论】:
标签: sql postgresql
如果在“最后一条记录”下你的意思是具有最新时间戳值的记录,那么试试这个:
my_query = client.query("
SELECT TIMESTAMP,
value,
card
FROM my_table
ORDER BY TIMESTAMP DESC
LIMIT 1
");
【讨论】:
SELECT id,value,card FROM my_table ORDER BY id DESC LIMIT 1;
CURRVAL(<sequence name>)
你可以使用
SELECT timestamp, value, card
FROM my_table
ORDER BY timestamp DESC
LIMIT 1
假设您还想按timestamp 排序?
【讨论】:
SELECT timestamp, value, card
FROM my_table
ORDER BY timestamp DESC
LIMIT 1;
但是,LIMIT 不是标准的,正如Wikipedia 所述,SQL 标准的核心功能并未明确定义 Null 的默认排序顺序。。最后,当多条记录共享最大时间戳时,只返回一行。
执行此操作的典型方法是检查没有任何行的时间戳高于我们检索到的任何行。
SELECT timestamp, value, card
FROM my_table t1
WHERE NOT EXISTS (
SELECT *
FROM my_table t2
WHERE t2.timestamp > t1.timestamp
);
这是我最喜欢的解决方案,也是我倾向于使用的解决方案。缺点是当我们看到这个查询时,我们的意图并不是很清楚。
为了避免这种情况,可以在子查询中使用 MAX 而不是相关性。
SELECT timestamp, value, card
FROM my_table
WHERE timestamp = (
SELECT MAX(timestamp)
FROM my_table
);
但是如果没有索引,则需要对数据进行两次传递,而前一个查询只需一次扫描即可找到解决方案。也就是说,除非必要,否则我们在设计查询时不应考虑性能,因为我们可以预期优化器会随着时间的推移而改进。然而,这种特殊的查询非常常用。
我不建议这样做,但也许你可以给你的老板或其他人留下好印象;-)
SELECT DISTINCT
first_value(timestamp) OVER w,
first_value(value) OVER w,
first_value(card) OVER w
FROM my_table
WINDOW w AS (ORDER BY timestamp DESC);
实际上,这表明一个简单的查询可以用多种方式表达(我可以想到其他几种方式),并且应该根据几个标准来选择一种或另一种形式,例如如:
【讨论】:
如果您接受小费,请在此表中创建一个 id,如 serial。该字段的默认值为:
nextval('table_name_field_seq'::regclass).
因此,您使用查询来调用最后一个寄存器。使用您的示例:
pg_query($connection, "SELECT currval('table_name_field_seq') AS id;
我希望这个提示对你有所帮助。
【讨论】:
nextval 没有返回的情况下返回错误'未在当前会话中调用,但您也不会看到其他会话中所做的更改。
假设您将“id”作为主键,则可以使用此查询最后插入的记录:
SELECT timestamp,value,card FROM my_table WHERE id=(select max(id) from my_table)
假设插入的每个新行都将使用表 id 的最大整数值。
【讨论】:
如果您的表没有整数自增等Id,也没有时间戳,您仍然可以通过以下查询获取表的最后一行。
select * from <tablename> offset ((select count(*) from <tablename>)-1)
例如,这可以让您搜索更新的平面文件,查找/确认先前版本的结束位置,并将剩余的行复制到您的表格中。
【讨论】:
使用下面的
SELECT timestamp, value, card
FROM my_table
ORDER BY timestamp DESC
LIMIT 1
【讨论】:
要获取最后一行,
按排序顺序获取最后一行:如果表中有指定时间/主键的列,
LIMIT 子句SELECT * FROM USERS ORDER BY CREATED_TIME DESC LIMIT 1;
FETCH 子句-Reference
SELECT * FROM USERS ORDER BY CREATED_TIME FETCH FIRST ROW ONLY;
获取行插入顺序中的最后一行:如果表中没有指定时间/任何唯一标识符的列
使用CTID系统列,其中ctid表示表中行的物理位置-Reference
SELECT * FROM USERS WHERE CTID = (SELECT MAX(CTID) FROM USERS);
考虑下表,
userid |username | createdtime |
1 | A | 1535012279455 |
2 | B | 1535042279423 | //as per created time, this is the last row
3 | C | 1535012279443 |
4 | D | 1535012212311 |
5 | E | 1535012254634 | //as per insertion order, this is the last row
查询 1 和 2 返回,
userid |username | createdtime |
2 | B | 1535042279423 |
当 3 返回时,
userid |username | createdtime |
5 | E | 1535012254634 |
注意:更新旧行时,它会删除旧行并更新数据并作为新行插入表中。因此,使用以下查询将返回最迟对其进行数据修改的元组。
现在更新一行,使用
UPDATE USERS SET USERNAME = 'Z' WHERE USERID='3'
表格变成了,
userid |username | createdtime |
1 | A | 1535012279455 |
2 | B | 1535042279423 |
4 | D | 1535012212311 |
5 | E | 1535012254634 |
3 | Z | 1535012279443 |
现在查询 3 返回了,
userid |username | createdtime |
3 | Z | 1535012279443 |
【讨论】:
这些都是很好的答案,但是如果您想要一个聚合函数来执行此操作以获取由任意查询生成的结果集中的最后一行,there's a standard way to do this(取自 Postgres wiki,但应该可以在任何符合合理要求的情况下工作十年或更久以前的 SQL 标准):
-- Create a function that always returns the last non-NULL item
CREATE OR REPLACE FUNCTION public.last_agg ( anyelement, anyelement )
RETURNS anyelement LANGUAGE SQL IMMUTABLE STRICT AS $$
SELECT $2;
$$;
-- And then wrap an aggregate around it
CREATE AGGREGATE public.LAST (
sfunc = public.last_agg,
basetype = anyelement,
stype = anyelement
);
如果您有合理的排序,通常最好使用select ... limit 1,但如果您需要在聚合中执行此操作并且希望避免子查询,这很有用。
另请参阅this question,了解这是自然答案的情况。
【讨论】:
列名在降序中起重要作用:
select <COLUMN_NAME1, COLUMN_NAME2> from >TABLENAME> ORDER BY <COLUMN_NAME THAT MENTIONS TIME> DESC LIMIT 1;
例如:下面提到的表(user_details)由列名“created_at”组成,该列具有该表的时间戳。
SELECT userid, username FROM user_details ORDER BY created_at DESC LIMIT 1;
【讨论】:
在 Oracle SQL 中,
select * from (select row_number() over (order by rowid desc) rn, emp.* from emp) where rn=1;
【讨论】:
select * from table_name LIMIT 1;
【讨论】: