monetdb select last n rows - sql

My monetdb table has over 100k rows. I want to select the last n rows from the table. Will it be possible to query only the last n records without scanning the entire table?

for Transact SQL:
SELECT *
FROM [your_table] AS tbl
ORDER BY 1 DESC
TOP n
or others (SQL Standard):
SELECT *
FROM [your_table] AS tbl
ORDER BY 1 DESC
LIMIT n

The only reliable way of doing this is by having a column with an increasing time stamp or id value that you can ORDER BY.
Especially if there are no deletes, MonetDB will notice that this column is sorted and use this fact to quickly locate the latest rows.

Related

Oracle select specific rows

Can we select specific rows to range in oracle? for example, I have a table of 100 rows I have to select only a range of 10 to 20-row numbers. Is it possible to do that
You can do with an auxiliary operation. Firstly number the rows by row_number() function and then order by them :
select * from
(
select row_number() over (order by 0) rn, t.*
from tab t
)
where rn between 10 and 20;
but this is not a stable operation, since SQL statements are unordered sets. Therefore it's better to define a unique identity column and order depending on it.
Replace zero in the order by clause with some columns of your table to be able to reach a rigid ordering criteria. If a primary key column exists, it might be better to include only it in the order by list.
would LIMIT and OFFSET work?
ie.
SELECT * FROM table
LIMIT 20
OFFSET 20
will read rows 20 -> 40. Is this what you are trying to do?

Performance issue when using ORDER BY dbms_random.value for Oracle database

I need to get 1000 random rows from a table and found solution for Oracle. But if I use this query when retrieving data from table containing large amount of rows it takes up to 3 minutes to complete:
SELECT column FROM
( SELECT column FROM table
ORDER BY dbms_random.value )
WHERE rownum <= 1000
It happens because all rows are selected and then all of them are ordered by random value when I need only 1000. Is there any workaround for such problem? Maybe using dbms_random.value along with some cursor that will pick random row.
I would do that in this manner:
SELECT column
FROM table sample (1)
where rownum <= 1000
--ORDER BY dbms_random.value
;
Will get a sample of 1 percent from table, stop at first 1000 (and, if needed, order randomly) .
It is possible to exist a better way to do want you want. This is what I'll try.

How to retrieve the last 2 records from table?

I have a table with n number of records
How can i retrieve the nth record and (n-1)th record from my table in SQL without using derived table ?
I have tried using ROWID as
select * from table where rowid in (select max(rowid) from table);
It is giving the nth record but i want the (n-1)th record also .
And is there any other method other than using max,derived table and pseudo columns
Thanks
You cannot depend on rowid to get you to the last row in the table. You need an auto-incrementing id or creation time to have the proper ordering.
You can use, for instance:
select *
from (select t.*, row_number() over (order by <id> desc) as seqnum
from t
) t
where seqnum <= 2
Although allowed in the syntax, the order by clause in a subquery is ignored (for instance http://docs.oracle.com/javadb/10.8.2.2/ref/rrefsqlj13658.html).
Just to be clear, rowids have nothing to do with the ordering of rows in a table. The Oracle documentation is quite clear that they specify a physical access path for the data (http://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#i6732). It is true that in an empty database, inserting records into a newtable will probably create a monotonically increasing sequence of row ids. But you cannot depend on this. The only guarantees with rowids are that they are unique within a table and are the fastest way to access a particular row.
I have to admit that I cannot find good documentation on Oracle handling or not handling order by's in subqueries in its most recent versions. ANSI SQL does not require compliant databases to support order by in subqueries. Oracle syntax allows it, and it seems to work in some cases, at least. My best guess is that it would probably work on a single processor, single threaded instance of Oracle, or if the data access is through an index. Once parallelism is introduced, the results would probably not be ordered. Since I started using Oracle (in the mid-1990s), I have been under the impression that order bys in subqueries are generally ignored. My advice would be to not depend on the functionality, until Oracle clearly states that it is supported.
select * from (select * from my_table order by rowid) where rownum <= 2
and for rows between N and M:
select * from (
select * from (
select * from my_table order by rowid
) where rownum <= M
) where rownum >= N
Try this
select top 2 * from table order by rowid desc
Assuming rowid as column in your table:
SELECT * FROM table ORDER BY rowid DESC LIMIT 2

Keep only N last records in SQLite database, sorted by date

I have an SQLite database that I need to do the following: Keep only last N records, sorted by date. How do you do that?
To delete all but the latest 10 records.
delete
from test
where id not in (
select id
from test
order by date desc
limit 10
)
According to the SQLite documentation:
If SQLite is compiled with the SQLITE_ENABLE_UPDATE_DELETE_LIMIT compile-time option, then the syntax of the DELETE statement is extended by the addition of optional ORDER BY and LIMIT clauses.
(...)
If the DELETE statement has an ORDER BY clause, then all rows that would be deleted in the absence of the LIMIT clause are sorted according to the ORDER BY. The first M rows, where M is the value found by evaluating the OFFSET clause expression, are skipped, and the following N, where N is the value of the LIMIT expression, are deleted. If there are less than N rows remaining after taking the OFFSET clause into account, or if the LIMIT clause evaluated to a negative value, then all remaining rows are deleted.
This would allow you to write:
DELETE FROM table WHERE expr ORDER BY date DESC LIMIT -1 OFFSET 10
to keep only the last 10 records, think inverted.
To delete the older 10 records:
DELETE FROM Table_name
WHERE date in (SELECT date FROM Table_name ORDER BY Date Desc Limit -1
OFFSET (select count(*)-10 from Table_name) );
Let me know how it worked for you!
Assuming you have an id column which is a sequential number (AUTO INCREMENT), you can use the following:
DELETE FROM table_name
WHERE id < (
SELECT MIN(id)
FROM (SELECT id
FROM table_name
ORDER BY id DESC
LIMIT num_of_records_to_keep))
The same query can be used when using a timestamp column (simply replace id with your timestamp column)
I wonder if this is faster or slower than Jackob solution. sqlitebrowser says 0ms for both...
DELETE FROM test WHERE date < ( SELECT date FROM test ORDER BY date DESC LIMIT 1 OFFSET 9 )

Are the results deterministic, if I partition SQL SELECT query without ORDER BY?

I have SQL SELECT query which returns a lot of rows, and I have to split it into several partitions. Ie, set max results to 10000 and iterate the rows calling the query select time with increasing first result (0, 10000, 20000). All the queries are done in same transaction, and data that my queries are fetching is not changing during the process (other data in those tables can change, though).
Is it ok to use just plain select:
select a from b where...
Or do I have to use order by with the select:
select a from b where ... order by c
In order to be sure that I will get all the rows? In other word, is it guaranteed that query without order by will always return the rows in the same order?
Adding order by to the query drops performance of the query dramatically.
I'm using Oracle, if that matters.
EDIT: Unfortunately I cannot take advantage of scrollable cursor.
Order is definitely not guaranteed without an order by clause, but whether or not your results will be deterministic (aside from the order) would depend on the where clause. For example, if you have a unique ID column and your where clause included a different filter range each time you access it, then you would have non-ordered deterministic results, i.e.:
select a from b where ID between 1 and 100
select a from b where ID between 101 and 200
select a from b where ID between 201 and 300
would all return distinct result sets, but order would not be any way guaranteed.
No, without order by it is not guaranteed that query will ALWAYS return the rows in the same order.
No guarantees unless you have an order by on the outermost query.
Bad SQL Server example, but same rules apply. Not guaranteed order even with inner query
SELECT
*
FROM
(
SELECT
*
FROM
Mytable
ORDER BY SomeCol
) foo
Use Limit
So you would do:
SELECT * FROM table ORDER BY id LIMIT 0,100
SELECT * FROM table ORDER BY id LIMIT 101,100
SELECT * FROM table ORDER BY id LIMIT 201,100
The LIMIT would be from which position you want to start and the second variable would be how many results you want to see.
Its a good pagnation trick.