SELECT all but the last 5 items in MySQL - mysql

I'm trying to run a query that will SELECT all but the 5 items in my table.
I'm currently using the following query to get the last 5 items.
SELECT * FROM articles ORDER BY id DESC LIMIT 5
And I would like another query to get all the other items, so excluding the last 5.

You select the last 5 items by conveniently sorting them in the reverse order.
SELECT * FROM articles ORDER BY id DESC LIMIT 5
LIMIT 5 is, in fact, a short form of LIMIT 0, 5.
You can use the same trick to skip the first 5 items and select the rest of them:
SELECT * FROM articles ORDER BY id DESC LIMIT 5, 1000000
Unfortunately MySQL doesn't provide a way to get all the rows after it skips the first 5 rows. You have to always tell it how many rows to return. I put a big number (1 million) in the query instead.
For both queries, the returned articles will be sorted in the descending order. If you need them in the ascending order you can save the smallest value of id returned by the first query and use it in the second query:
SELECT * FROM articles WHERE id < [put the saved id here] ORDER BY id ASC
There is no need for limit on the second query and you can even sort the records by other columns if you need.

You can do it like this:
SELECT * FROM articles
ORDER BY id ASC
LIMIT (SELECT count(*)-5 FROM articles)
You can also use NOT EXISTS() or NOT IN() but I'll have to see the columns names to adjust the sql for you, something like this:
SELECT * FROM articles a
WHERE a.id NOT IN(SELECT id FROM articles ORDER BY id DESC LIMIT 5)
Can also be done with a left join:
SELECT t.* FROM articles t
LEFT JOIN (SELECT id FROM articles ORDER BY id DESC LIMIT 5) s
ON(t.id = s.id)
WHERE s.id is null
Note that if the table has more then one key(the ID column) you have to add it to the relations of the ON clause.

Try
SELECT * FROM articles a NOT EXIST (SELECT * FROM articles b WHERE a.id=b.id ORDER BY id DESC LIMIT 5);

Related

I am trying to do a Order by after a Limit Query

So this is my First Question here, so please forgive me if something is wrong.
I am trying to do Order by a limit query.
So there is a Customers table of 90 records.
I want Limit 3 records query to be done first and then sort this query records by a column called ContactName.
I think it would be a nested. The nested works fine in SQL server, but don't know how to do in MySQL.
Limit Query:
Select * from customers limit 3;
Order by after limit Query ( My guess, but this doesn't works):
Select * from (Select * from customers limit 3) Order by ContactName;
Please Help. Thanks
you just need this
Select * from customers Order by ContactName limit 3;
When you use a subquery in a FROM or JOIN clause, you're required to give it an alias.
Select *
from (Select * from customers limit 3) AS x
Order by ContactName;
Note that using LIMIT 3 without ORDER BY in the subquery doesn't really make much sense -- you don't know how it's going to choose the 3 customers to return. It would make more sense if you were choosing the 3 newest customers and then ordering them by name:
Select *
from (
Select *
from customers
order by registration_date DESC
limit 3) AS x
Order by ContactName;

MySQL: First select 10 newest rows in descending PK order, then the rest of records alphabetically

I have a simple table USERS:
id | name
----+------
Can you help me with the query that would fetch all rows from the table and:
a) Place 10 rows with highest PK values on top, in id DESC order;
b) Place all remaining rows ordered by name ASC order.
Thank you!
This is a bit of a tricky question. The approach I would take is a join approach. Identify the primary keys for the first group using a join (this is happily fast because you are working with primary keys). Then use the match to that table for the order by:
select t.*
from table t left outer join
(select id
from table t
order by id desc
limit 10
) t10
on t.id = t10.id
order by t10.id desc,
t.name asc;
First question would be: do you really need this in one single query? I'm really not seeing the use case for such a query to be honest.
It'd be easier to just fetch the 10 biggest ids (storing somewhere the 10th biggest), and then fetch the rest in ascending name order (with a restriction on ids being smaller than the 10th biggest).
Otherwise in a single query, something like this would work, but it doesn't seem very efficient to me (maybe someone will have a better idea).
(
SELECT
id, name
from
USERS
ORDER BY id DESC LIMIT 0,10
)
UNION
(
SELECT
id, name
from
USERS
WHERE
id NOT IN (
SELECT id, name from USERS ORDER BY id DESC LIMIT 0,10
)
ORDER BY name ASC
)
(or maybe with a NOT EXISTS - the inner query will be different - instead of the NOT IN)

Is this an inefficient query?

Assuming table1 and table2 both have a large number of rows (ie several hundred thousand), is the following an inefficient query?
Edit: Order by field added.
SELECT * FROM (
SELECT title, updated FROM table1
UNION
SELECT title, updated FROM table2
) AS query
ORDER BY updated DESC
LIMIT 25
If you absolutely need distinct results, another possibility is to use union all and a group by clause instead:
SELECT title FROM (
SELECT title FROM table1 group by title
UNION ALL
SELECT title FROM table2 group by title
) AS query
group by title
LIMIT 25;
Testing this without the limit clause on an indexed ID column from two tables with ~920K rows each in a test database (at $work) resulted in a bit over a second with the query above and about 17 seconds via a union.
this should be even faster - but then I see no ORDER BY so what 25 records do you actually want?
SELECT * FROM (
SELECT title FROM table1 LIMIT 25
UNION
SELECT title FROM table2 LIMIT 25
) AS query
LIMIT 25
UNION must make an extra pass to fetch the distinct records, so you should use UNION ALL.
Yes, use order by and limits in the inner queries.
SELECT * FROM (
(SELECT title FROM table1 ORDER BY title ASC LIMIT C)
UNION
(SELECT title FROM table2 ORDER BY title ASC LIMIT C)
) AS query
LIMIT 25
This will only go through C rows instead of N (hundreds of thousands). The ORDER BY is necessary and should be on an indexed column.
C is a heuristic constant that should be tuned according to the domain. If you only expect a few duplicates, C=50-100 is probably ok.
You can also find out this for yourself by using EXPLAIN.

Get another order after limit

Imagine I've a table 'users' with two fields: 'age' and 'name'. I want to retrieve the top ten older users and then I want this list of ten sorted by name.
Is it possible to do it with MySQL?
I've tried this: (doesn't work)
SELECT * FROM users order by age, name limit 10
Use a subselect:
SELECT * FROM
(
SELECT *
FROM users
ORDER BY age DESC
LIMIT 10
) AS T1
ORDER BY name
The inner select finds the 10 rows you want to return, and the outer select puts them in the correct order.

Fetch the top 5 records from 2 tables each using single query

I want to fetch the top 10 records from 2 tables which have id as reference id using single query.
For example, I have student and Student_details tables.
Now I want to fetch top 5 records of student table and top 5 records of Student_details table.
Do you want to have the results from both tables combined in 1 result set?
If so, then use
SELECT student.*, student_details.*
FROM student, student_details
WHERE student.id = student_details.student_id
ORDER BY id ASC LIMIT 5;
SELECT * FROM student ORDER BY id ASC LIMIT 5;
SELECT * FROM student_details ORDER BY id ASC LIMIT 5;
SELECT * FROM STUDENTS ORDER BY ID LIMIT 5
SELECT * FROM table WHERE ... ORDER BY ... DESC/ASC LIMIT 5;
Do it twice.
This is not possible! You could create a temporary table and somehow try to match the fields of one table to match the field of the other if they both have almost the same number of fields - only then you could use a single query to get the top 5 results of both tables using one query. But even then this would lead to more than a single query (because you had to create the temp table first).
The best you can do is to use two queries:
SELECT * FROM student ORDER BY student.id LIMIT 5;
SELECT * FROM student_details ORDER BY student_details.id LIMIT 5;