Get a row, then others order by id - mysql

How can I get a specific row (id=x) and then the reminders? Something like:
SELECT * FROM table ORDER BY id=5 FIRST THAN id DESC
I tried to use UNION ALL, like:
(SELECT * FROM table WHERE id=5)
UNION ALL
(SELECT * FROM table WHERE id!=5 ORDER BY id DESC)
but the result is unexpected since the second SELECT doesn't return the registers ordered by id (desc). In addition, in this way is neccessary to write much more.

SELECT * FROM table ORDER BY id = 5 DESC, id ASC
This will give you something like: 5, 1, 2, 3, 4, 6, 7, ...

You can put more than one clause on the order by line:
select *
from t
order by (case when id = 5 then 1 else 0 end) desc, id desc
Also, tables and result sets in SQL are unordered. The one exception is the use of order by for a result set. I wouldn't expect the union all method to work.

This will give you '5's first, then 'not 5's
SELECT *
FROM table
ORDER BY case when id=5 then 0 else 1 end ASC

Related

Order by FIELD along with subquery?

I want to order the query results by specific values.
Seems like I can use this:
SELECT
column
FROM
table
ORDER BY
IF(
FIELD(
id,
3,1,2
) = 0,
1,
0
) ASC,
FIELD(
id,
3,1,2
)
My problem is that 3,1,2 comes from another table column. Replacing 3,1,2 with (SELECT column from...) is not working properly. Because the SELECT returns the result as "3,1,2" and not as 3,1,2
I can also extract 3,1,2 one by one, but in this case i get error Subquery returns more than 1 row.
What's the solution here ?
Suppose that the statement that returns the values 3, 1, 2 is something like this:
SELECT somecolumn FROM sometable ORDER BY someothercolumn
then you can use GROUP_CONCAT() to create a comma separated string that contains these values:
SELECT GROUP_CONCAT(somecolumn ORDER BY someothercolumn) col FROM sometable
and then use FIND_IN_SET() instead of FIELD():
SELECT t.column
FROM table t
CROSS JOIN (SELECT GROUP_CONCAT(somecolumn col ORDER BY someothercolumn) FROM sometable) s
ORDER BY
SUBSTRING_INDEX(t.id, s.col) = 0,
SUBSTRING_INDEX(t.id, s.col)
I hope that I understood the logic that you want to apply to sort the table with your ORDER BY clause.

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

MYSQL: Return results ONLY for the first true encountered SELECT expression

Desired result:
Return results ONLY for the first true encountered SELECT expression.
Explanation:
So, I have three different SELECT expresions:
SELECT * FROM table WHERE column1 = 'sometext' AND column2='1'
SELECT * FROM table WHERE column1 = 'someothertext' AND column2='2'
SELECT * FROM table WHERE column1 = 'somethirdtext' AND column2='3'
I want to have the results from 1. If 1. is returning NULL, I would like result from select number 2. If Select number 2. is returning NULL, I would like to use select number 3. and so on.
Please note that I am expecting more than one row to be returned for each condition that is true - and I only want the result from either SELECT 1) 2) or 3) (in that order)
It is important to only return results from the one single SELECT expression, so even if 2. and 3. would return something, I would only like results from 1.
The code I have right now is following that expected logic BUT when a I have more than one rows being returned by some of the below SELECTS, it gives me error:
1242 - Subquery returns more than 1 row
The code right now:
SELECT IFNULL( (SELECT * FROM table WHERE column = 'sometext'), IFNULL( (SELECT * FROM table WHERE column = 'someothertext'), IFNULL( (SELECT * FROM table WHERE column = 'somethirdtext'), 0 ) ) )
You're looking for COALESCE function.
SELECT COALESCE(
(SELECT col FROM t WHERE `column` = 'sometext'),
(SELECT col FROM t WHERE `column` = 'someothertext'),
(SELECT col FROM t WHERE `column` = 'somethirdtext')
);
-please, note that subquery should not return more than 1 row/column.
I would approach this slightly differently, since you can only return one row per condition anyway, I would use the following to limit the number of selects done:
SELECT *
FROM table
WHERE column IN ('sometext', 'someothertext', 'somethirdtext')
ORDER BY CASE column
WHEN 'sometext' THEN 1
WHEN 'someothertext' THEN 2
WHEN 'somethirdtext' THEN 3
END
LIMIT 1;
As pointed out in the comments, you can use FIELD for the sort too:
SELECT *
FROM table
WHERE column IN ('sometext', 'someothertext', 'somethirdtext')
ORDER BY FIELD(column, 'sometext', 'someothertext', 'somethirdtext')
LIMIT 1;
I think you can get multiple rows per condition using the following:
SELECT T.*
FROM Table T
INNER JOIN
( SELECT Column
FROM Table
WHERE column IN ('sometext', 'someothertext', 'somethirdtext')
ORDER BY FIELD(column, 'sometext', 'someothertext', 'somethirdtext')
LIMIT 1
) MinT
ON MinT.Column = T.Column;
Basically the subquery MinT does the same as before, ordering by whichever condition matches. Then gets the value for the column of the first match and limits the whole table to this value.
Example on SQL Fiddle
SELECT t.*
FROM
( SELECT o.column1, o.column2
FROM
( SELECT 1 AS ord, 'sometext' AS column1, '1' AS column2 UNION ALL
SELECT 2, 'someothertext', '2' UNION ALL
SELECT 3, 'somethirdtext', '3'
) AS o
WHERE EXISTS
( SELECT 1
FROM table AS td
WHERE td.column1 = o.column1
AND td.column2 = o.column2
)
ORDER BY o.ord
LIMIT 1
) AS d
JOIN
table AS t
ON t.column1 = d.column1
AND t.column2 = d.column2 ;
MySQL isn't my daily db so I might be off on this, but can't you just use LIMIT 1 on your subqueries?

Order mysql query in the same order I provide the OR statements in

Here's a query:
SELECT *
FROM table
WHERE id = 1
OR id = 100
OR id = 50
Note that I provided the ids in this order: 1,100,50.
I want the rows to come back in that order: 1,100,50.
Currently, i comes back 1,50,100 - basically in ascending order. Assume the rows in the table were inserted in ascending order also.
Use the MySQL specific FIND_IN_SET function:
SELECT t.*
FROM table t
WHERE t.id IN (1, 100, 50)
ORDER BY FIND_IN_SET(CAST(t.id AS VARCHAR(8)), '1,100,50')
Another way to approach this would put the list in a subquery:
select table.*
from table join
(select 1 as id, 1 as ordering union all
select 100 as id, 2 as ordering union all
select 50 as id, 3 as ordering
) list
on table.id = list.id
order by list.ordering
You can just do this with ORDER BY:
ORDER BY
id = 1 DESC, id = 100 DESC, id = 50 DESC
0 is before 1 in ORDER BY.
Try this
SELECT *
FROM new
WHERE ID =1
OR ID =100
OR ID =50
ORDER BY ID=1 DESC,ID=100 DESC,ID=50 DESC ;
http://www.sqlfiddle.com/#!2/796e2/5
... WHERE id IN (x,y,x) ORDER BY FIELD (id,x,y,z)

MySQL reverse order without DESC

SELECT id FROM table LIMIT 8, 3
results in 8,9,10
but I need 10,9,8
How can you do this? If you add "ORDER BY id DESC" it gets 3,2,1
Put your query in a subselect and then reverse the order in the outer select:
SELECT id from (
SELECT id FROM table ORDER BY id LIMIT 8, 3
) AS T1 ORDER BY id DESC
Test data:
CREATE TABLE table1 (id INT NOT NULL);
INSERT INTO table1 (id) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
SELECT id from (
SELECT id FROM table1 ORDER BY id LIMIT 8, 3
) AS T1 ORDER BY id DESC
Result:
10
9
8
Note that the ORDER BY in the subquery is required otherwise the order is undefined. Thanks to Lasse for pointing this out!
First of all, if you're not ordering at all, that you got 8,9,10 right now might be related to the index used. Are you sure this isn't going to change in the future?
What I'm getting at is that unless you specify an order, you should not rely on it being the one you want.
So I would definitely add an order to that select to specify what you want. Otherwise you're only saying "give me 3 numbers from this table", not "give me 3 numbers from this table according to these rules". Why is 3,2,1 wrong but 8,9,10 right? You're not specifying.
Anyway, to answer your question, you must order after the limit, which means a subselect:
SELECT id FROM (
SELECT id FROM table LIMIT 8, 3
) AS dummy ORDER BY id DESC
However, I would try this SQL instead, related to the part about specifying:
SELECT id FROM (
SELECT id FROM table ORDER BY id LIMIT 8, 3
) AS dummy ORDER BY id DESC