How ORDER BY works in MySQL? - mysql

assume there is a table with 100 million records in it with this schema:
+---------+---------+------+
| user_id | post_id | date |
+---------+---------+------+
We want to have latest 30 records which user with #1 is posted.
SELECT * FROM users_posts WHERE user_id = 1 ORDER BY date DESC LIMIT 30
How MySQL search in table ? Does it search all rows ( full scan ) finding all matches THEN ordering them by date?
if Yes( Full Scan ), how can we edit this query to limit it to search latest records till finds 30 matches. ( to increase reading speed and have better performance )
thanks in advanced.

If you want the best performance for this query:
SELECT *
FROM users_posts
WHERE user_id = 1
ORDER BY date DESC;
Then you want an index on users_posts(user_id, date). This will allow the SQL engine to only use the index to define the set of rows being used. First, it will use user_id to satisfy the where clause. Then it will use the date part for the order by. It will still have to look up the records in the original data pages, in order to get all the columns needed for the select.
If you want to limit this to 30 rows, then add limit 30:
SELECT *
FROM users_posts
WHERE user_id = 1
ORDER BY date DESC
LIMIT 30;
With the above index, this will improve performance. With no index, the engine will have to scan all the data, sort the data that matches the where clause, and then apply the limit -- in other words, it won't be much of an improvement in performance.

Related

get MAX date using limit and offset

Is there a way to use limit offset and get the most recent (MAX) date from that group
My table: column_id, column_data, column_date
I've tried
SELECT max(column_date) FROM table_name limit 2000 offset 22000
I'm trying to get the most recent date in the 2000 rows returned using the offset. In other words, I'm looking for the last date modified in each group of 2000.
The table structure above has 100,000 rows. each query gets 2000 rows and I would like to retrieve the most recent date from the 2000 rows (using offset).
You must extract the whole group then find MAX() over it:
SELECT MAX(date_column)
FROM ( SELECT date_column
FROM source_table
ORDER BY some_expression /* compulsory! must provide rows uniqueness! */
LIMIT #rows_in_group OFFSET #group_offset ) AS subquery

How can i make order by faster?

When i use ORDER BY in large table (160000 rows) like this:
select HomeTeam,AwayTeam,FTR,FTHG,FTAG,HS,`AS`,`Date`,Elo1A,Elo1B,Elo2A,Elo2B,Elo3A,Elo3B,Elo4A,Elo4B,nElo1A,nElo1B,nElo2A,
nElo2B,nElo3A,nElo3B,nElo4A,nElo4B from historic
where (HomeTeam='Crystal Palace' or AwayTeam='Crystal Palace') and datediff('1994-08-20',Date)>0 order by `Date` desc limit 1
fetch duration is 1.078 sec / 0.000 sec
When i use without ORDER BY like this:
select HomeTeam,AwayTeam,FTR,FTHG,FTAG,HS,`AS`,`Date`,Elo1A,Elo1B,Elo2A,Elo2B,Elo3A,Elo3B,Elo4A,Elo4B,nElo1A,nElo1B,nElo2A,
nElo2B,nElo3A,nElo3B,nElo4A,nElo4B from historic
where (HomeTeam='Crystal Palace' or AwayTeam='Crystal Palace') and datediff('1994-08-20',Date)>0 limit 1
fetch duration is 0.187 sec / 0.000 sec
Problem is that without ORDER BY i get wrong result:
Crystal Palace Tranmere 1993-08-14
but correct is with ORDER BY like this:
Crystal Palace Watford 1994-05-08
How can i avoid ORDER BY or somehow smarter call last match from current match?
As per our conversation in comments you have created index on date field and getting performance by it-
Further you can try below query which may provide you better performance-
SELECT HomeTeam,AwayTeam,FTR,FTHG,FTAG,HS,`AS`,`Date`,Elo1A,Elo1B,Elo2A,Elo2B,Elo3A,Elo3B,Elo4A,Elo4B,nElo1A,nElo1B,nElo2A,
nElo2B,nElo3A,nElo3B,nElo4A,nElo4B FROM historic
WHERE (HomeTeam='Crystal Palace' OR AwayTeam='Crystal Palace') and `Date` < '1994-08-20' ORDER BY `Date` DESC LIMIT 1;
Note: Here I just remove function from date field so that it can use index to filter data also.

SQL: Skip entries in an order without knowing total entry amount

The title is a bit confusing, but I'm wondering if there is a way to do a query like this:
SELECT * FROM table ORDER BY timestamp LIMIT 10
and then only take the ones after the 10th one (or none if there are less than or equal to 10 entries).
EDIT I guess another way to do this would be to order them by timestamp, descending, and then somehow limit to 0, (total-someNumber).
By specifying an OFFSET you can get the rows after a specified number. You combine this with limit.
In MySQL you achieve this with LIMIT [offset], limit.
Example - get 10 records after the oldest 10 records:
SELECT * FROM table ORDER BY timestamp LIMIT 10, 10; # Retrieve rows 11-20
Example - get 20 records after the newest 5 records:
SELECT * FROM table ORDER BY timestamp DESC LIMIT 5, 20; # Retrieve rows 6-25
If you want to get ALL rows after a certain number (eg. 10) then you pass an arbitrarily big number for the limit since it is required by the clause:
SELECT * FROM table ORDER BY timestamp LIMIT 10,18446744073709551615; # Retrieve rows 11-BIGINT
Note: 18446744073709551615 is the maximum of an unsigned BIGINT and is provided as the solution within the MySQL documentation.
See:
http://dev.mysql.com/doc/refman/5.5/en/select.html
I'd try something like this and then just add a where clause that skips the first n (n=10 in this case) rows.
i.e. using the linked example:
SELECT
*
FROM
(select #n := #n + 1 RowNumber, t.* from (select #n:=0) initvars, tbl t)
WHERE
RowNumber > 10

Sqlite Query select statement with sorted result respecting the OFFSET

I want to make a sqlite query in such a way that the result should be sorted which has a LIMIT and the OFFSET. But the OFFSET should work in synch a manner that it should discard the last records from the result.
SELECT * FROM TempTable WHERE CLASS = 1 ORDER BY Date ASC LIMIT 100 OFFSET 5;
The above query just ignores the first 5 records from the table and give the remaining records. But instead I want it to ignore the first 5 latest entries.
Note:- the first 5 latest entries means since I am sorting it by date it should IGNORE the latest record inserted in the table respecting the date.
Sort backwards, with OFFSET 5 and resort again:
SELECT * FROM (
SELECT * FROM TempTable WHERE CLASS = 1 ORDER BY Date DESC LIMIT 100 OFFSET 5
) ORDER BY Date ASC;

mysql select with this query then pad out with this query?

I am trying to do a mysql query to select some news stories from a table, now the key is I always need 5 results.
so I was hoping to be able to pad out my results with another where clause ie
select * from here where this = 1
if there is < 5 results then select * from here where this = 2
limit [how ever many we are short say the first query brings back 3 results this should bring back 2]
Now I've looked at using a union to do this but without outside help ie from php and another query to count the results I don't think it is possible, I know I could simply use php to do this, and will probably end up doing that, but I was just wondering if what I am trying to do is possible with one mysql query?
EDIT:
also it needs to order by date but they are not really posted in order so
order by date get upto 5 where this = 1 and if there isn't 5 pad it out with the remainder of where this = 2 also ordered by date.
Another Shameful Edit:
ask a silly question lol... it was my sleep deprivation I just assumed there was data in the table and the previous coder was using unions to do all sorts of stuff, making me think it was more complex than it should be
SELECT *
FROM
news
WHERE
( this = 45 || this= 0 )
AND
active = '1'
ORDER BY
this ASC,
date_added DESC
LIMIT 5
How about -
SELECT *
FROM here
WHERE this < 5 -- added this WHERE clause based on the idea that there will be at least one item per this
ORDER BY this ASC, `date` ASC
LIMIT 5;
Or are you after the five results then being sorted by date again -
SELECT *
FROM (
SELECT *
FROM here
WHERE this < 5 -- added this WHERE clause based on the idea that there will be at least one item per this
ORDER BY this ASC, `date` ASC
LIMIT 5
) AS tmp
ORDER BY `date` ASC
You could combine the where clauses and use limit :
select * FROM here WHERE this = 1 OR this = 2 ORDER BY this LIMIT 5
Even in there were 15 records where this is equal to 1 this would only bring back 5 records ...