如何从sql查询中获取第一个和最后一个记录?
我在PostgreSQL中有一个表,我用几个条件运行查询,返回多个行,按其中一列排序。一般来说它是:如何从sql查询中获取第一个和最后一个记录?
SELECT <some columns>
FROM mytable
<maybe some joins here>
WHERE <various conditions>
ORDER BY date DESC
现在我只获得第一,并从该查询的最后一行感兴趣。我可以在数据库之外获得它们(这是我实际做的),但是想知道为了获得更好的性能,我不应该从数据库中只获得我实际上感兴趣的2条记录。
如果是这样,我该如何修改我的查询?
[警告:可能不是这样做的最有效的方法]:
(SELECT <some columns>
FROM mytable
<maybe some joins here>
WHERE <various conditions>
ORDER BY date DESC
LIMIT 1)
UNION ALL
(SELECT <some columns>
FROM mytable
<maybe some joins here>
WHERE <various conditions>
ORDER BY date ASC
LIMIT 1)
我认为'Top'关键字仅适用于SQL Server,MySQL/Postgre使用'Limit' – Robo 2009-09-28 04:28:06
你是对的。我会编辑我的并投票给你。 – 2009-09-28 04:30:21
使用UNION ALL会使这一点稍微更快,因为它会删除对重复项的检查。如果第一行和最后一行当然是相同的,UNION将只返回一行,UNION ALL将两次返回同一行,它在工作方式上会有所不同。 – 2009-09-28 08:16:12
第一条记录:
SELECT <some columns> FROM mytable
<maybe some joins here>
WHERE <various conditions>
ORDER BY date ASC
LIMIT 1
最后一个记录:
SELECT <some columns> FROM mytable
<maybe some joins here>
WHERE <various conditions>
ORDER BY date DESC
LIMIT 1
其他评论中提到的UNION ALL方法肯定会比发出两个查询更快。 – 2009-09-28 08:16:45
SELECT * FROM TABLE_NAME WHERE ROWID=(SELECT MIN(ROWID) FROM TABLE_NAME)
UNION
SELECT * FROM TABLE_NAME WHERE ROWID=(SELECT MAX(ROWID) FROM TABLE_NAME)
或
SELECT * FROM TABLE_NAME WHERE ROWID=(SELECT MIN(ROWID) FROM TABLE_NAME)
OR ROWID=(SELECT MAX(ROWID) FROM TABLE_NAME)
PostgreSQL没有一个'rowid',这就是所谓的'ctid'存在(并没有Oracle的ROWID也不PostgreSQL的CTID保证任何顺序) – 2012-08-26 21:13:50
为什么不把这个简单: 'SELECT * FROM TABLE_NAME WHERE ROWID =(SELECT MIN (rowid)FROM TABLE_NAME) OR rowid =(SELECT MAX(rowid)FROM TABLE_NAME)' – 2012-10-11 13:53:03
你可能想试试这个,可能比做两个查询速度快:
select <some columns>
from (
SELECT <some columns>,
row_number() over (order by date desc) as rn,
count(*) over() as total_count
FROM mytable
<maybe some joins here>
WHERE <various conditions>
) t
where rn = 1
or rn = total_count
ORDER BY date DESC
有趣。我没有意识到这一点。只是测试过它,当然,这都是真的。感谢您的洞察力。 – DrFriedParts 2016-03-12 09:19:17
最后一条记录:
SELECT * FROM `aboutus` order by id desc limit 1
第一个记录:
SELECT * FROM `aboutus` order by id asc limit 1
这对于PostgreSQL来说是无效的SQL(它使用标准双引号'''来引用对象名称 - 在这里它们根本不需要) – 2012-09-03 06:32:10
Works,thanks!有人知道这是多么高效吗? – Souleiman 2013-04-20 21:50:56
@souleiman每个查询查询计划器将尽可能快地使用适当的索引并返回O(log(N))...但是,在2个单独的查询中这样做会比一个查询更慢和/或效率更低如果你总是*想要*两者* OP的第一个和最后一个记录表示,只需在两个查询之间使用UNION ALL(更快)(如果你不想重复,则使用UNION)。 – DrFriedParts 2016-03-12 05:16:38
select *
from {Table_Name}
where {x_column_name}=(
select d.{x_column_name}
from (
select rownum as rno,{x_column_name}
from {Table_Name})d
where d.rno=(
select count(*)
from {Table_Name}));
为什么不使用order by asc极限1和反向排序通过desc限制1 ..
?
SELECT
MIN(Column), MAX(Column), UserId
FROM
Table_Name
WHERE
(Conditions)
GROUP BY
UserId DESC
或
SELECT
MAX(Column)
FROM
TableName
WHERE
(Filter)
UNION ALL
SELECT
MIN(Column)
FROM
TableName AS Tablename1
WHERE
(Filter)
ORDER BY
Column
-- Create a function that always returns the first non-NULL item
CREATE OR REPLACE FUNCTION public.first_agg (anyelement, anyelement)
RETURNS anyelement LANGUAGE SQL IMMUTABLE STRICT AS $$
SELECT $1;
$$;
-- And then wrap an aggregate around it
CREATE AGGREGATE public.FIRST (
sfunc = public.first_agg,
basetype = anyelement,
stype = anyelement
);
-- 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
);
得到它从这里: https://wiki.postgresql.org/wiki/First/last_(aggregate)
在做,直到如今,都要经过扫描两次,一个是首先暴露的方式第一行和第一行。
使用窗口函数“ROW_NUMBER()OVER(...)”加上“WITHQUERY”,您只能扫描一次并获取这两个项目。
窗口功能: https://www.postgresql.org/docs/9.6/static/functions-window.html
使用查询: https://www.postgresql.org/docs/9.6/static/queries-with.html
例子:
WITH scan_plan AS (
SELECT
<some columns>,
ROW_NUMBER() OVER (ORDER BY date DESC) AS first_row, /*It's logical required to be the same as major query*/
ROW_NUMBER() OVER (ORDER BY date ASC) AS last_row /*It's rigth, needs to be the inverse*/
FROM mytable
<maybe some joins here>
WHERE <various conditions>
ORDER BY date DESC)
SELECT
<some columns>
FROM scan_plan
WHERE scan_plan.first_row = 1 OR scan_plan.last_row = 1;
在这样你会做关系的过滤和数据操作一次。
在两种方式上尝试一下EXPLAIN ANALYZE。
使用集合函数MIN&MAX:http://www.postgresql.org/docs/8.2/static/tutorial-agg.html – 2009-09-28 04:24:19
@rexem:min&max不会在几列上工作 - 它们将工作只有在您按此专栏订购时才可以在单栏中显示。 – 2009-09-28 04:57:32
您可能还想看看'SELECT DISTINCT ON(...)... ORDER BY ...'。参见[PostgreSQL文档](https://www.postgresql.org/docs/current/static/sql-select.html)。 – RhinoDevel 2016-08-11 09:42:27