SQL pagination when ordering by modified date - sql

I have a bunch of records that I want to paginate by reverse modified date. From what I can tell, using a simple query pulls the same sub-set of records and then sorts only those by date.
Something like this:
SELECT * FROM items WHERE status='1' ORDER BY modified_date DESC LIMIT start,count
Would an index help me? Or am I going to have to figure out some way to code this perhaps adding a column that somehow keeps track of modified_date in reverse order?

An index on (status, modified_date) might help. See indexes dos and donts.

This query looks good for me. It does the following:
Find records with status = 1
Order them by modified_date DESC
Return count records starting from start
So if you need to show first page, you should set start=0. For second page it'll be start=count, for third start=2*count and so on.
Or do you have performance problems with this?

Its a hack and I haven't tried it because I can't reproduce your problem and may not perform well but this may work for you
SELECT *
FROM (SELECT *
FROM items
WHERE status = '1'
ORDER BY modified_date desc ) t
LIMIT START, COUNT

You can add a column that holds a TIMESTAMP then set the auto-update property on it, so that it is properly updated. Finally, create an index for this column. Your query will look something like this:
SELECT *
FROM items
WHERE status='1'
ORDER BY 'timestamp' DESC
LIMIT start,count

Related

How to get a distinct result ordered by a different column? SQL Postgresql

I'm trying to figure the best way to perform this query in postgresql. I have a messages table and I want to grab the last message a user received from each distinct user. I need to select everything from the row.
I would think this is where I want to group by the senders id "msgfromid", but when I do this it complains that I haven't included everything from my select statement in my group by statement, but I only want to group by the one column, not all of them. So if I try to use Distinct on the one column it forces me to order by the 'distinct on' column first ("msgfromid") which prevents me from being able to get the correct row I need (ordered by the last message sent from the sender "msgsenttime").
My goal is to make this as efficient as possible on my server and database.
This is what I have right now, not working. (This is a sub-query of another query I use to join relevant information afterwards but I figure that is irrelevant)
SELECT DISTINCT ON ("msgfromid") "msgfromid", "msgid", "msgtoid", "msgsenttime", "msgreadtime", "msgcontent", "msgreportstatus", "senderun", "recipientun"
FROM "messages"
WHERE "msgtoid" = ?
ORDER BY "msgsenttime" desc, "msgfromid"
I thought maybe if I pre-ordered them in a sub-query it would work but it just seems to randomly pick one anyway, and this can't be very efficient, even if it were to work, since I'm pulling every message out to begin with, right?:
SELECT DISTINCT ON ("msgfromid") "msgfromid", "msgid", "msgtoid", "msgsenttime", "msgreadtime", "msgcontent", "msgreportstatus", "senderun", "recipientun"
FROM
(
SELECT * FROM "messages"
WHERE "msgtoid" = ?
ORDER BY "msgsenttime" desc
) as "mqo"
Thanks for any help.
Your order by keys are in the wrong order:
SELECT DISTINCT ON ("msgfromid") m.*
FROM "messages" m
WHERE "msgtoid" = ?
ORDER BY "msgfromid", "msgsenttime" desc;
For DISTINCT ON, the keys in parentheses need to be the first keys in the ORDER BY.
If you want the final result ordered in a different way, then you need to use a subquery, with a different ORDER BY on the outer query.

sql query push certain records to top

Im looping through forum topics with a mySQL query, but id like records with the field sticky being 1 to always be pushed to the top, or first, then it looping through the rest.
How could I do this?
At the moment they are ordered like ORDER BY last_post DESC (last_post being a datetime)
I think ORDER BY sticky DESC, last_post DESC should work.

opposite to top

I'm working with sql server 2005.
I have a view which sorts its columns according to order date. I call:
SELECT TOP 1 [OrderDate]
FROM [ordersview]
to get the latest time. How do I get the earliest time?
SELECT TOP 1 OrderDate FROM ordersview ORDER BY OrderDate DESC
Also:
SELECT MIN(OrderDate) FROM ordersview
Use a descending ordering:
select top 1 OrderDate from ordersview order by OrderDate desc
I think,
this is little bit tricky question.
Every body will say for white is opposite black.
And for first is it last.
but when u are not specifying initial order
what is really the first.
I think it is internal/vendor specific thing.
So both answers are right ,but actually not answering really your question.
I'm not really mssql-guy but think that your select will return random
row (maybe depending on inserting sequence , or same internal db thing like rowId).
And what is opposite for random ?
One more thing is that, ordering is pretty demanding(resource/performance) function ,
for such thing u should have index on column.
And basically when u are doing select like that u should thing about real paging
not only one item .
But then the result will have different order then original one ( so ... )

SQL Simple ORDER BY

I'm new to SQL and I don't think this question should be hard to answer. I have a high-score table for a game that contains the columns name, score, and rank. I want to know how I can order the table by descending order each time a new score is added so the table can always stay ordered by score.
I know this is the wrong way of doing this, but I hope this makes my point kind of clearer.
UPDATE `HSTable`.`Highscores` ORDER BY `Highscores`.`score` DESC;
What is the correct way of approaching this?
One more thing, is there a way I can set it so that the ranking value always stays where it's suppose to be from the SQL, for example, 1st place is always at the top regardless the score?
generally we use order by while fetching data from table
so we use
SELECT * FROM `HSTable` ORDER BY `score` DESC
Use a ranking function like RANK or DENSE_RANK to rank the results. For better performance you can add a clustered index that starts with score descending.
You can get ordered results using SELECT clause:
SELECT * FROM `HSTable` ORDER BY `score` DESC
I don't believe the order of the data in your database table should really matter because when you query the data you can sort it any which way you would like. What is the reason why you want to have the data stored in the database in the correct order?
That is not the correct way to select records in SQL. Use this instead:
SELECT * FROM `tablename` ORDER BY `id` DESC

Efficient SQL to count an occurrence in the latest X rows

For example I have:
create table a (i int);
Assume there are 10k rows.
I want to count 0's in the last 20 rows.
Something like:
select count(*) from (select i from a limit 20) where i = 0;
Is that possible to make it more efficient? Like a single SQL statement or something?
PS. DB is SQLite3 if that matters at all...
UPDATE
PPS. No need to group by anything in this instance, assume the table that is literally 1 column (and presumably the internal DB row_ID or something). I'm just curious if this is possible to do without the nested selects?
You'll need to order by something in order to determine the last 20 rows. When you say last, do you mean by date, by ID, ...?
Something like this should work:
select count(*)
from (
select i
from a
order by j desc
limit 20
) where i = 0;
If you do not remove rows from the table, you may try the following hacky query:
SELECT COUNT(*) as cnt
FROM A
WHERE
ROWID > (SELECT MAX(ROWID)-20 FROM A)
AND i=0;
It operates with ROWIDs only. As the documentation says: Rows are stored in rowid order.
You need to remember to order by when you use limit, otherwise the result is indeterminate. To get the latest rows added, you need to include a column with the insertion date, then you can use that. Without this column you cannot guarantee that you will get the latest rows.
To make it efficient you should ensure that there is an index on the column you order by, possibly even a clustered index.
I'm afraid that you need a nested select to be able to count and restrict to last X rows at a time, because something like this
SELECT count(*) FROM a GROUP BY i HAVING i = 0
will count 0's, but in ALL table records, because a LIMIT in this query will basically have no effect.
However, you can optimize making COUNT(i) as it is faster to COUNT only one field than 2 or more (in this case your table will have 2 fields, i and rowid, that is automatically created by SQLite in PKless tables)