PostgreSQL:How get last rows from a select query - sql

See the below example,
create table data(name varchar, value int);
insert into data values('joe',1);
insert into data values('bob',2);
insert into data values('jane',3);
insert into data values('anne',4);
insert into data values('kate',5);
And if I Execute
select * from data limit 2;
Will Get
name | value
------+-------
joe | 1
bob | 2
(2 rows)
So,How Can I Get the Last 2 Rows in select * from data?
What I'm expecting is....
name | value
------+-------
anne | 4
kate | 5
(2 rows)

You have two options according to your need i.e,
select * from data order by value desc limit 2
Or
LIMIT and OFFSET
if you want the 4th and 5th row just offset the first 3 so that the 4th row becomes the start of our set and you can specify a limit to say that you only want 2 rows from that.
select * from data offset 3 limit 2;
/* The order of LIMIT and OFFSET does not matter. This gives the same result */
select * from data limit 2 offset 3;

I know I'm answering a six year old question and I know the accepted answer says to use an offset, however that's only going to be useful if you know the length of the table. Looking at the wording of the question and the example given, I assumed that like myself, the author wanted the last entries in a table based on an id or other value in the order that they were entered.
The best solution I've found so far that orders the values as expected is using a subquery as follows:
SELECT * FROM ( SELECT * FROM data ORDER BY VALUE DESC LIMIT 2) AS _ ORDER BY VALUE ASC;
You'd substitute VALUE for whichever column you'd want to sort by to get the "last" entries. In my experience, this method is an order of magnitude quicker than using a count to find an offset.

To get the x last rows, example with x=10,
use offset alone, with count:
SELECT *
FROM data
ORDER BY value ASC
OFFSET (SELECT count(*) FROM DATA)-10
I let you check if the offset is not negative...

Make use of Order by Clause
select * from data order by value desc limit 2;
OR
select top 2 * from data order by value desc ;

You can achieve it using Order by clause desc
SELECT *
FROM data
ORDER BY value DESC limit 2;

like does Krishraj Rana you can try this function for get the last row with "limit 1" and order by "x col" desc, complete it "by x_col desc limit 1".

Related

How to select rows between x and y in Redshift

I can select the TOP rows from a Redshift table by using the TOP clause. But I would like to select the rows between, say, 10 and 20. I am using the ORDER BY clause, so the resultset is consistent.
How do I do that?
I would ideally like something like:
SELECT * BETWEEN 10 AND 20
FROM <tablename>
The more traditional method in Redshift would be LIMIT/OFFSET. For the second set of 10 rows:
select t.*
from t
order by XXX
limit 10 offset 9;
Note that the offset is one less than the row where you want to start (i.e. offset 0 = "first row").
This is also the syntax used in Postgres.

I want to find the longest varchar in a specific column of a SQL Server table

Here's an example:
ID = INT IDENTITY
DESC = VARCHAR(5000)
ID | Desc
---|-----
1 | a
2 | aaa
3 | aa
The SQL query here should return 3 and the word itself i.e., aaa? Since the longest value is aaa with 3 characters?
The output should be:
aaa 3
You can use order by and limit the results to one row:
select description, len(description)
from t
order by len(description) desc
offset 0 row fetch first 1 row only;
Or use:
select top (1) description, len(description)
from t
order by len(description) desc;
With OFFSET & FETCH:
OFFSET is specifying how many rows from the top of the result set you will ignore ...
And then the FETCH is used to limit the result to the number of rows you specify.
The combination of this two will return the desired result because the result set is ordered by len(descr).
select descr, len(descr)
from test
order by len(descr) desc
OFFSET 0 ROWS
fetch first 1 rows only;
With TOP:
TOP will limit the reultset to the number of rows you specify. In this example 1. Because it is ordered by the lenght of the column desc then the first row will be the one you are looking for.
select top 1 descr, len(descr)
from test
order by len(descr) desc
HERE IS A DEMO for both examples
Note for the end:
Use aliases (I will demonstrate on one of this two examples)
select descr as Description, len(descr) "Description length"
from test
order by len(descr) desc
OFFSET 0 ROWS
fetch first 1 rows only;
You can put them between double quotes or not, use keyword as or not, it is up to you but the result looks better with them.
Both ROW and ROWS keyword is ok for OFFSET and FETCH clause. So what ever you want to use you can...
You can try TOP as shown below. Here is the official documentation of TOP (Transact-SQL).
Select
top 1 Id, description, len(description) as MaxLength
from YourTable order by len(description) desc
Live Demo
This will do what you want on Oracle (one of the tags on the question):
SELECT descript,length(descript)
FROM t WHERE length(descript)=( SELECT max(length(descript)) FROM t);
Keep in mind that if there are two (or more) records with that length, you will get them all. You could add a AND rownum < 2 clause but that will give you which ever entry the database chooses to give.
If you want the first record of those with the longest field, a subquery will be required:
SELECT descript,length(descript) from (
select descript from t order by length(descript) desc, descript asc)
WHERE rownum < 2;
There is also the offset 0 row fetch... version listed earlier:
SQL> select descript, length(descript)
2 from t
3 order by length(descript) desc
4 offset 0 row fetch first 1 row only;
DESCRIPT LENGTH(DESCRIPT)
-------------------- ----------------
defg 4
Mind you, this only works on my "12.2.0.1.0" Oracle. If I try the same thing on my "11.2.0.4.0" Oracle, I get "ORA-00933: SQL command not properly ended" with that last line. Apparently this is newer, maybe that is why I have never seen it before.

pagination and filtering on a very large table in postgresql (keyset pagination?)

I have a scientific database with currently 4,300,000 records. It's a scientific database, and an API is feeding it. In june 2020, I will probably have about 100,000,000 records.
This is de layout of the table 'output':
ID | sensor_ID | speed | velocity | direction
-----------------------------------------------------
1 | 1 | 10 | 1 | up
2 | 2 | 12 | 2 | up
3 | 2 | 11.5 | 1.5 | down
4 | 1 | 9.5 | 0.8 | down
5 | 3 | 11 | 0.75 | up
...
BTW, this is dummy data. But output is a table with 5 columns: ID, sensor_ID, speed, velocity and direction.
What I want to achieve is a decent pagination and filter method. I want to create a website (in nodejs) where this +4,000,000 records (for now) will be displayed, 10,000 records per page. I also want to be able to filter on sensor_ID, speed, velocity or direction.
For now, I have this query for selecting specific rows:
SELECT * FROM output ORDER BY ID DESC OFFSET 0 LIMIT 10000 // first 10,000 rows
SELECT * FROM output ORDER BY ID DESC OFFSET 10000 LIMIT 10000 // next 10,000 rows
...
I'm searching for some information/tips about creating a decent pagination method. For now, it's still quiet fast the way I do it, but I think it will be a lot slower when we hit +50,000,000 records.
First of all, I found this page: https://www.citusdata.com/blog/2016/03/30/five-ways-to-paginate/. I'm interested in the keyset pagination. But to be honest, I have no clue how to start.
What I think I must do:
Create an index on the ID-field:
CREATE UNIQUE INDEX index_id ON output USING btree (ID)
I also found this page: https://leopard.in.ua/2014/10/11/postgresql-paginattion. When you scroll down to "Improvement #2: The Seek Method", you can see that they dropped the OFFSET-clause, and are using a WHERE-clause. I also see that they are using the last insert ID in their query:
SELECT * FROM output WHERE ID < <last_insert_id_here> ORDER BY ID DESC LIMIT 10000
I do not fully understand this. For the first page, I need the very last insert ID. Then I fetch the 10,000 newest records. But after that, to get the second page, I don't need the very last insert ID, I need the 10,000th last insert ID (I guess).
Can someone give me a good explanation about pagination and filtering in a fast way.
The stuff I'm using:
- postgresql
- pgadmin (for database management)
- node.js (latest version)
Thanks everyone! And have a nice 2020!
EDIT 1: I have no clue, but could massiveJS (https://massivejs.org/) be something good to use? And should I use it on ALL queries, or only on the pagination queries?
EDIT 2: I THINK I got it figured out a little bit (correct me if I'm wrong).
Let's say I have 100,000 records:
1) Get the last inserted ID
2) Use this last inserted ID to fetch the last 10,000 records
SELECT * FROM output WHERE ID < 100000 ORDER BY ID DESC LIMIT 10000 // last insert ID is here 100,000 because I have 100,000 records
3) Show the 10,000 records but also save the insert ID of the 10,000the record to use in the next query
4) Get the next 10,000 records with the new last insert id
SELECT * FROM output WHERE ID < 90000 ORDER BY ID DESC LIMIT 10000 // 90,000 is the very last insert id - 10,000
5) ...
Is this correct?
Here's how I handle this. For the first page I fetch, I use
SELECT id, col, col, col
FROM output
ORDER BY id DESC
LIMIT 10000
Then, in my client program (node.js) I capture the id value from the last row of the result set. When I need the next page, I do this.
SELECT id, col, col, col
FROM output
WHERE id < my_captured_id_value
ORDER BY id DESC
This exploits the index. And it works correctly even if you have deleted some rows from the table.
By the way, you probably want a descending index if your first pagination page has the largest ids. CREATE UNIQUE INDEX index_id ON output USING btree (ID DESC).
Pro tip SELECT * is harmful to performance on large databases. Always list the columns you actually need.
In keyset pagination you should set WHERE clause on what you want to set in ORDER BY clause , and for DESC you should use < and vice versa.
For the first page you can use something like this:
SELECT Col1, Col2, Col3
FROM db.tbl
WHERE Col3 LIKE '%search_term%'
ORDER BY Col1 DESC , Col2 ASC
LIMIT 10000
and for next page , you should send value of Col1 and Col2 from last row of the result to the query like this:
SELECT Col1, Col2, Col3
FROM db.tbl
WHERE Col3 LIKE '%search_term%'
AND ( Col1 < Col1_last_row_value AND Col2 > Col2_last_row_value)
ORDER BY Col1 DESC , Col2 ASC
LIMIT 10000
and in the server or client side you should check if your query bring back any result or not , if not that means you are done and the loading-icon of "infinite scroll" has to be hidden

How to subtract the content of a column of two rows

I have a table like this
and I want to return the difference between the two rows
SQL tables represent unordered sets. There is no ordering, unless a column specifies the ordering.
So, you can get the two values using MAX() and MIN(). This should do what you want:
select max(nbaction) - min(nbaction)
from t;
EDIT:
Given your actual problem, you have multiple choices. Here is one:
SELECT (SELECT nbaction
FROM analyse_page_fait
WHERE operateurdimid = 2
ORDER BY datedimid DESC
FETCH FIRST 1 ROW ONLY
) -
(SELECT nbaction
FROM analyse_page_fait
WHERE operateurdimid = 2
ORDER BY datedimid DESC
OFFSET 1
FETCH FIRST 1 ROW ONLY
) as diff

SQL - Min difference between two integer fields

How I can get min difference between two integer fields(value_0 - value)?
value_0 >= value always
value_0 | value
-------------------
15 | 10
12 | 10
15 | 11
11 | 11
Try this:
SELECT MIN(value_0-value) as MinDiff
FROM TableName
WHERE value_0>=value
With the sample data you have given,
Output is 0. (11-11)
See demo in SQL Fiddle.
Read more about MIN() here.
Here is one way:
select min(value_0 - value)
from table t;
This is pretty basic SQL. If you want to see other values on the same row as the minimum, use order by and choose one row:
select (value_0 - value)
from table t
order by (value_0 - value)
limit 1;
The limit 1 works in some databases for getting one row. Others use top 1 in the select clause. Or fetch first 1 rows only. Or even something else.