Select multiple rows by position without id - mysql

In MySql I have a complex SELECT which returns a table of about 500k rows and without primary key.
I would like to select 10 rows based on the different position they have in the resulting table, as efficiently as possible.
I tried using LIMIT:
SELECT * FROM table_name LIMIT 5,1;
efficient but select only one row.
I tried with UNION and LIMIT, but I have to do the complex SELECT several times:
(SELECT * FROM table_name LIMIT 5,1)
UNION
(SELECT * FROM table_name LIMIT 1000,1)
UNION
(SELECT * FROM table_name LIMIT 50000,1)
...
Is there a more efficient way to get what I want?

In order to get the positions you must sort the data; there is no way around that. So, number your rows by the desired order and pick the positions you want:
select *
from
(
select t.*, row_number() over (order by ...) as rn
from table_name t
) numbered
where rn in (6, 1001, 50001);

Related

ORDER BY not working properly with UNION in MySQL

I have 2 tables t1 and t2 as follows
I want to select the results from both the tables with a UNION and sort on qty column. The query that I have written is
(SELECT * FROM t1)
UNION ALL
(SELECT * FROM t2)
ORDER BY qty ASC;
That gives me the below result
Can some 1 tell me what is going wrong here? As per the query I should get qty column sorted in ascending order. I have also tried
(SELECT * FROM t1
UNION ALL
SELECT * FROM t2)
ORDER BY qty ASC;
No luck with that either. If I do sort with id or item it works perfectly fine. This is really frustrating. Please help.
Possible duplicate of Sorting varchar field numerically in MySQL
Try
(SELECT * FROM t1
UNION ALL
SELECT * FROM t2)
ORDER BY CAST(qty as SIGNED INTEGER) ASC;

How do I select some rows and then others in MySQL?

I have this query, it works but I'm not sure if it's the best approach and I don't get what I want.
I need to select the query contained in the "IN" clause first, then union with others. Entire row returned must be 40.
SELECT *
FROM (
SELECT * FROM tbl_x a WHERE id IN(11,20,30)
UNION ALL
SELECT * FROM tbl_x b WHERE exam_group='jpx' AND subject='chemistry'
) ab
GROUP BY id LIMIT 40
The next query should to return same data in simple way:
SELECT *
FROM tbl_x
WHERE
id IN (11,20,30)
OR (exam_group='jpx' AND subject='chemistry')
ORDER BY id IN (11,20,30) DESC, id
LIMIT 40;

SELECT from external data in MySQL

Let's consider a made up example
SELECT id, name, score.score FROM
someTable,
(select someTableId, count(*) as score FROM SecondTable GROUP BY someTableId) as score
WHERE score.someTableId == id
ORDER BY score.score DESC
Let's now assume that I have a backend computing my scoring, and that I would like to remove the subquery and insert my own data instead. I would like to know how to do this.
I would like to do something like (this is the question, because what's below doesn't work):
SELECT id, name, score.score FROM
someTable,
((12,324), (1, 342)) as score(id, score)
WHERE score.someTableId == id
ORDER BY score.score DESC
Here is an example of external data substitution to a subquery:
SELECT * FROM users WHERE id IN (SELECT user_id FROM posts WHERE thread_id = 12 GROUP BY user_id);
Without a subquery and with external data:
SELECT * FROM users WHERE id IN (1,2,3);
If I understood you correctly :
SELECT id, name, score.score FROM
someTable,
(SELECT 12 as someTableId,324 as score UNION ALL SELECT 1, 342 <UNION ALL....>) as score(id, score)
WHERE score.someTableId == id
ORDER BY score.score DESC
Thats the only way you can do it, it doesn't actually replace the the subquery, but it replace the select from the table and can improve performance if thats what you are looking for.
In MySQL you don't need to specify a from clause like a dummy table when you are just looking to fetch dummy data.
Other DBMS require a dummy table name (typically DUAL) but in MySQL it's rather straightforward:
SELECT 12 AS id, 324 AS score
UNION ALL SELECT 2, 65
UNION ALL SELECT 3, 598
UNION ALL SELECT 4, 244
You can use this as any other result-set.

UNION two ordered MySQL statements

I have a table with 3 columns (id, name, code) and 10 rows. Some of the rows don't have a code so that column is empty for some. What I'm trying to accomplish is SELECT the rows with code column not empty first ordered by last inserted followed by all rows with code column empty ordered by last inserted.
I have tried
(SELECT * from tablename WHERE code <> '' ORDER BY ID DESC) UNION
(SELECT * from tablename WHERE code = '' ORDER BY ID DESC)
The UNION works but the order does not. I have read here about other questions and found out adding ORDER BY like I added will not work and I should add it at the end but that would not help me accomplish what I want and will mix rows that have a code with rows that don't.
Is there a way to succeed with what I'm looking for?
I think you just need to put your sort logic in the ORDER BY clause
SELECT id, name, code
FROM tablename
ORDER BY code = '', ID desc;
Try this:
SELECT * FROM
(
(SELECT * from tablename WHERE code <> '' ORDER BY ID DESC)
UNION
(SELECT * from tablename WHERE code = '' ORDER BY ID DESC)
)tab ORDER BY ID DESC;
Or
SELECT * from tablename ORDER BY code DESC,ID DESC
Change ASC/DESC as per you want it to show

SQL - ORDER BY ASC LIMIT 1 excludes multiple same results - best method?

I'm still learning SQL so I was wondering if there is a better way of doing the following.
I need to get row data for the lowest and highest values in a column (lets call it columnA).
I would use:
SELECT *
FROM table
ORDER BY columnA
DESC LIMIT 1
Problem is I get only one result due to the LIMIT 1 but there may be identical lowest / highest values in ColumnA that have different values in the other columns. I need those other rows too.
There is SELECT(MAX) but I believe that will also only produce one row of data.
The ways I can think do this are by putting the highest / lowest columnA values into a variable and then back into a second query OR use a LEFT JOIN on alias tables to do this in single query but is there any more direct method?
The simplest way is to perform a sub-query:
SELECT * FROM MyTable WHERE columnA = (SELECT MAX(columnA) FROM MyTable);
You can even query both extremes at once:
SELECT * FROM MyTable
WHERE columnA = (SELECT MAX(columnA) FROM MyTable);
OR columnA = (SELECT MIN(columnA) FROM MyTable);
I haven't tested the next one (don't know if MySQL supports UNION in
sub-queries), but it should work as well, might be a bit more
efficient (depending on your data size).
SELECT * FROM MyTable
WHERE columnA IN (
SELECT MAX(columnA) FROM MyTable
UNION
SELECT MIN(columnA) FROM MyTable
);
Another option is :
SELECT *
FROM MyTable m1
WHERE not exists (select 1 from MyTable where columnA > m1.columnA)