I need to find the index in a table of a specific row and also select it.
I need both, the index and the row.
Any ideas?
EDIT: by 'index' I refer to position in the table after being ordered.
This question could be a duplicate, but I don't know what to look for.
SQL database are fundamentally unordered. There is no index or row number in a table. Unless you explicitly order the results with ORDER BY in a SELECT clause there is no guarantee that the rows will be returned to you in the same order in two successive queries.
To uniquely identify a row, you must ensure that you know which column (or combination of column values) are uniquely identify a row and include these terms in the WHERE clause.
Related
I have a database with an PRIMARY KEY INTEGER AUTOINCREMENT column named id and a condition flag column, call it condition which is an INTEGER.
I would like to be able to SELECT a given number of rows N where conditon=1. That is easy enough to query (for example if N=10):
SELECT data FROM table_name WHERE condition=1 LIMIT 10;
However I would like to be guaranteed that the rows I receive are also those rows with the smallest values of id from the full set of rows where condition=1. For example if rows with id between 1 and 20 have condition=1 I would like my query to be guaranteed to return rows with id=1 - 10.
My understanding is that ORDER BY is completed after the query so I don't think including ORDER BY id would make this a guarantee. Is there a way to guarantee this?
Well you are wrong:
SELECT data FROM table_name WHERE condition=1 ORDER BY id LIMIT 10;
is what you need.
It will sort the rows you need and then the limit is applied.
From http://www.sqlitetutorial.net/sqlite-limit/
SQLite LIMIT and ORDER BY clause
We typically use the LIMIT clause with ORDER BY clause, because we are
interested in getting the numberof rows in a specified order, not in
unspecified order.
The ORDER BY clause appears before the LIMIT clause in the SELECT
statement.
SQLite sorts the result set before getting the number of
rows specified in the LIMIT clause.
I have a table that is actually a ranking list. I want to give user a chance to rearrange that top the way he wants, ergo, allow him to move the rows in that table. Should I create a separate column that would hold the place, or can it be done using embedded order in table?
The documentation says:
If a SELECT statement that returns more than one row does not have an ORDER BY clause, the order in which the rows are returned is undefined.
(This is true for all SQL databases.)
So you cannot rely on the order that the rows happen to be stored in; you have to use some value in some table column.
I just want to clarify: if you insert a row to a table in sqlite, it appends it to the table, but -- as I learned -- the table is unordered, so there is really not true way to insert a row into the middle of an "ordered table," right?
Is there even a way to make an ordered table without first created a table and then using '...ORDER BY name/id/etc' (i.e. when you insert something it puts itself in the right place)?
SQLite tables are actually stored in rowid order, but this is unlikely to help you because it is unlikely that there is a gap where you want it.
Furthermore, the order in which rows are stored does not matter because there is no guarantee that this is the order in which they are returned.
When you want to SELECT rows in a specific order, you must use ORDER BY.
If your query is too slow, an index on the sorting column might help.
I have similar situation like question below.
Mysql speed up max() group by
SELECT MAX(id) id, cid FROM table GROUP BY cid
To optimize above query (shown in the question), creating index(cid, id) does the trick.
However, when I add a column that is not indexed to SELECT, query speed drastically slows down.
For example,
SELECT MAX(id) id, cid, newcolumn FROM table GROUP BY cid
If I create index(cid, id, newcolumn), query time comes back to minimal. It seems I should index all the columns I select while using GROUP BY.
Is there any way other than indexing all the columns to be select?
When all the columns used in the query are part of the index (which is then called a covering index), SQLite can get all values from the index and does not need to access the table itself.
When adding a column that is not indexed, each record must be looked up in both the index and the table.
Furthermore, the order of the records in the table is unlikely to be the same as the order in the index, so the table's pages are not read in order, and are read multiple times, which means that caching will not work as well.
The newcolumn values must be read from either the table or an index; there is no other mechanism to store data.
tl;dr: no
Ok I have a sqlite db, that has roughly 100 rows. It is kind of a strange thing that I'm trying to do, but I need to insert a new row between each of the existing rows.
I have been trying to use the Insert statement as follows, but haven't had any luck:
insert into t1(column1) values("hello") where id%2 == 0
So I'm basically trying to use the %-operator to tell me if the id is even or odd. For every even id number, I'd like to insert a new row.
What am I missing? What can I do differently? How can I insert a new row into every other row and have the index updated as well?
Thanks
Your question assumes that the rows have some kind of built-in order to them, and that you can insert rows between other rows. That's not true.
It is true that rows have an order on disk, and that the id column is usually assigned in order, but that's an implementation detail. When you perform a query, the database is free to return the rows in any order it chooses, unless you specify what you want with an ORDER BY clause.
Now, I'm assuming what you really want is to insert rows between the existing rows in id order. One way to get what you want would look like this:
UPDATE t1 SET id = id * 2
INSERT INTO t1 (id, column) SELECT id+1, "hello" FROM t1
The UPDATE would double the ids of all the existing rows (so 1,2,3 becomes 2,4,6); then the INSERT would perform a query on t1 and use the result to insert a new set of rows with id values one more than the existing rows (so 2,4,6 becomes 3,5,7).
I haven't tested the above statements, so I don't know if they would work or if they require some extra trickery (like a temporary table) since we are querying and updating the same table in one statement. Also I may have made a syntax error.
Don't consider the rows as pre-ordered in the database. A database will store them as they come in, or according to an index. It's your task to order them on retrieval (i.e. when you query for data) according to your needs.