MySQL Orderby a number, Nulls last - mysql

Currently I am doing a very basic OrderBy in my statement.
SELECT * FROM tablename WHERE visible=1 ORDER BY position ASC, id DESC
The problem with this is that NULL entries for 'position' are treated as 0. Therefore all entries with position as NULL appear before those with 1,2,3,4. eg:
NULL, NULL, NULL, 1, 2, 3, 4
Is there a way to achieve the following ordering:
1, 2, 3, 4, NULL, NULL, NULL.

MySQL has an undocumented syntax to sort nulls last. Place a minus sign (-) before the column name and switch the ASC to DESC:
SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC, id DESC
It is essentially the inverse of position DESC placing the NULL values last but otherwise the same as position ASC.
A good reference is here http://troels.arvin.dk/db/rdbms#select-order_by

I found this to be a good solution for the most part:
SELECT * FROM table ORDER BY ISNULL(field), field ASC;

NULL LAST
SELECT * FROM table_name ORDER BY id IS NULL, id ASC

Something like
SELECT * FROM tablename where visible=1 ORDER BY COALESCE(position, 999999999) ASC, id DESC
Replace 999999999 with what ever the max value for the field is

That's simple. You just need to order twice:
first step, order NULLs
second step, order your field.
SELECT * FROM table_name
ORDER BY ISNULL(field_name), field_name;
It works with any types, including JSON.

You can swap out instances of NULL with a different value to sort them first (like 0 or -1) or last (a large number or a letter)...
SELECT field1, IF(field2 IS NULL, 9999, field2) as ordered_field2
FROM tablename
WHERE visible = 1
ORDER BY ordered_field2 ASC, id DESC

Try using this query:
SELECT * FROM tablename
WHERE visible=1
ORDER BY
CASE WHEN position IS NULL THEN 1 ELSE 0 END ASC,id DESC

This works well for me as well.
ORDER BY ISNULL(field), field = 0 ASC;
Returns
1
2
3
0
0
null
null

You can coalesce your NULLs in the ORDER BY statement:
select * from tablename
where <conditions>
order by
coalesce(position, 0) ASC,
id DESC
If you want the NULLs to sort on the bottom, try coalesce(position, 100000). (Make the second number bigger than all of the other position's in the db.)

For a DATE column you can use:
NULLS last:
ORDER BY IFNULL(`myDate`, '9999-12-31') ASC
Blanks last:
ORDER BY IF(`myDate` = '', '9999-12-31', `myDate`) ASC

SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC

To achieve following result :
1, 2, 3, 4, NULL, NULL, NULL.
USE syntax, place -(minus sign) before field name and use inverse order_type(Like: If you want order by ASC order then use DESC or if you want DESC order then use ASC)
SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC

This is working fine:
SELECT * FROM tablename ORDER BY position = 0, position ASC;
position
1
2
3
0
0

Why don't you order by NULLS LAST?
SELECT *
FROM tablename
WHERE visible = 1
ORDER BY position ASC NULLS LAST, id DESC

Related

Query to Display records except Initial Record

For my project, i have a requirement where i have to display all the records in descending order except the first record. I am kind of messed up. Anyways, i have tried the following:
SELECT * FROM ins_nr nl WHERE nl.nl_status = '2' ORDER BY nl.nl_id DESC
Here, i have a table called ins_nr which will display all the records with status 2 and the id which is the primary key(unique). It is displaying in desc order perfectly.
I dont want the first record from the top alone. What should i do? How to modify the above query..?
Use OFFSET. Then you can skip 1 records and select the remaining ones until the end.
Example:
SELECT * FROM ins_nr nl WHERE nl.nl_status = '2'
ORDER BY nl.nl_id DESC LIMIT 99999999999 OFFSET 1;
OR ( You could also use a shorter syntax to achieve the same result: )
$sql = "SELECT * FROM table_name LIMIT 1, 999999999";
You can generate dynamic rownum and filter on it to omit the first row, e.g.:
SELECT *
FROM (
SELECT nl.*, #r := #r + 1 AS `rn`
FROM ins_nr nl, (SELECT #r := 0)
WHERE nl.nl_status = '2'
ORDER BY nl.nl_id DESC
) a
WHERE a.rn > 1;
Another way is to get the max id from subquery and put it in a where clausole
You are looking for the offset clause. This looks like:
SELECT *
FROM ins_nr nl
WHERE nl.nl_status = '2'
ORDER BY nl.nl_id DESC
LIMIT 999999999 OFFET 1;
Unfortunately, LIMIT is required. For this situation, it is traditional to just put in a very large number.
Also, if nl_status is numeric, then use nl.nl_status = 2. Don't compare strings to numbers.

Order an array with null values last [duplicate]

Currently I am doing a very basic OrderBy in my statement.
SELECT * FROM tablename WHERE visible=1 ORDER BY position ASC, id DESC
The problem with this is that NULL entries for 'position' are treated as 0. Therefore all entries with position as NULL appear before those with 1,2,3,4. eg:
NULL, NULL, NULL, 1, 2, 3, 4
Is there a way to achieve the following ordering:
1, 2, 3, 4, NULL, NULL, NULL.
MySQL has an undocumented syntax to sort nulls last. Place a minus sign (-) before the column name and switch the ASC to DESC:
SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC, id DESC
It is essentially the inverse of position DESC placing the NULL values last but otherwise the same as position ASC.
A good reference is here http://troels.arvin.dk/db/rdbms#select-order_by
I found this to be a good solution for the most part:
SELECT * FROM table ORDER BY ISNULL(field), field ASC;
NULL LAST
SELECT * FROM table_name ORDER BY id IS NULL, id ASC
Something like
SELECT * FROM tablename where visible=1 ORDER BY COALESCE(position, 999999999) ASC, id DESC
Replace 999999999 with what ever the max value for the field is
That's simple. You just need to order twice:
first step, order NULLs
second step, order your field.
SELECT * FROM table_name
ORDER BY ISNULL(field_name), field_name;
It works with any types, including JSON.
You can swap out instances of NULL with a different value to sort them first (like 0 or -1) or last (a large number or a letter)...
SELECT field1, IF(field2 IS NULL, 9999, field2) as ordered_field2
FROM tablename
WHERE visible = 1
ORDER BY ordered_field2 ASC, id DESC
Try using this query:
SELECT * FROM tablename
WHERE visible=1
ORDER BY
CASE WHEN position IS NULL THEN 1 ELSE 0 END ASC,id DESC
This works well for me as well.
ORDER BY ISNULL(field), field = 0 ASC;
Returns
1
2
3
0
0
null
null
You can coalesce your NULLs in the ORDER BY statement:
select * from tablename
where <conditions>
order by
coalesce(position, 0) ASC,
id DESC
If you want the NULLs to sort on the bottom, try coalesce(position, 100000). (Make the second number bigger than all of the other position's in the db.)
For a DATE column you can use:
NULLS last:
ORDER BY IFNULL(`myDate`, '9999-12-31') ASC
Blanks last:
ORDER BY IF(`myDate` = '', '9999-12-31', `myDate`) ASC
SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC
To achieve following result :
1, 2, 3, 4, NULL, NULL, NULL.
USE syntax, place -(minus sign) before field name and use inverse order_type(Like: If you want order by ASC order then use DESC or if you want DESC order then use ASC)
SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC
This is working fine:
SELECT * FROM tablename ORDER BY position = 0, position ASC;
position
1
2
3
0
0
Why don't you order by NULLS LAST?
SELECT *
FROM tablename
WHERE visible = 1
ORDER BY position ASC NULLS LAST, id DESC

Orderby MYSQL Syntax Wrong Data

I have a Table with a Column 'Rechnungnr' and 'Date'
Example 2016/204, 2016/202, 2016/100, 2015/12, 2016/231
and i need the last highest number. Here -> 2016/231.
SELECT * FROM TABLE Where YEAR(Date) = '2016' ORDER BY length(`Rechnungnr`) DESC LIMIT 1
But thats not working :(
Greetz, Malte
Use a combination of char_length() and the value of rechnungnr to get the max value this way:
SELECT * FROM TABLE
Where YEAR(Date) = 2016 ORDER BY char_length(`Rechnungnr`) DESC, `Rechnungnr` DESC LIMIT 1
char_length() will order the results by the number of characters within Rechnungnr field, and then within the equally long strings, we order by the value of the field itself.
Try using column name date surrounded by backtics
SELECT * FROM TABLE Where YEAR(`Date`) = '2016' ORDER BY length(`Rechnungnr`) DESC LIMIT 1
With your existing data set (if I understand the schema correctly) you can try something like this to get the day of year, cast it to an int and then sort on it:
SELECT *, CAST(RIGHT(LENGTH(`Rechnungnr`) - (INSTR(`Rechnungnr`, '/') + 1)) AS UNSIGNED) AS `DayOfYear` FROM TABLE Where YEAR(Date) = '2016' ORDER BY `DayOfYear` DESC LIMIT 1

SQL Multi Order by Count with Criteria

I want to query standings from MotoGP Race result
my sql is
SELECT `Rider`, `Team`, `Bike`,SUM(`Points`)
FROM `table_name`
WHERE `Year` = 2015 AND `Classes` = "MotoGP"
GROUP BY `Year`,`Rider`
HAVING SUM(`Points`)
ORDER BY SUM(`Points`) DESC
If 2 or more riders have same SUM('Points'), the next order is by number of 1st race position.
I put the race position on 'Pos' field.
Pos value: 1,2,3,4,5 ...
Please help for the 2nd order. Thank you
You just need to change the HAVING clause:
ORDER BY SUM(`Points`) DESC,
SUM(RacePosition = 1) DESC
For multiple positions, I think you need to add the condition for each one:
ORDER BY SUM(`Points`) DESC,
SUM(RacePosition = 1) DESC,
SUM(RacePosition = 2) DESC,
SUM(RacePosition = 3) DESC
At some point, perhaps SUM(RacePosition) would do what you want.

SQL: UNION realestate priorities offers

i'm trying to write a sql query to list all offers from database but first to retrive priorities NOT NULL order by rand then priorities NULL order by id.
I`ve made some kind of this:
(SELECT anunt_lista_id
FROM anunturi__lista
WHERE anunt_lista_is_prioritar IS NOT NULL
ORDER BY RAND())
UNION
(SELECT anunt_lista_id
FROM anunturi__lista
WHERE anunt_lista_is_prioritar IS NULL
ORDER BY anunt_lista_id ASC)
LIMIT 100
but ORDER BY is ignored, no one is applied.
There is another way to this and using another way to do RAND() because as i know this is too slow?
ORDER BY in individual parts of UNION is only useful when you add a LIMIT clause to that specific part, otherwise it is ignored.
From the docs:
To apply ORDER BY or LIMIT to an individual SELECT, place the clause
inside the parentheses that enclose the SELECT:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
However, use of ORDER BY for individual SELECT statements implies
nothing about the order in which the rows appear in the final result
because UNION by default produces an unordered set of rows. Therefore,
the use of ORDER BY in this context is typically in conjunction with
LIMIT, so that it is used to determine the subset of the selected rows
to retrieve for the SELECT, even though it does not necessarily affect
the order of those rows in the final UNION result. If ORDER BY appears
without LIMIT in a SELECT, it is optimized away because it will have
no effect anyway.
If you want the first part of the results to be sorted first, you have to workaround it in some way:
(SELECT anunt_lista_id
FROM anunturi__lista
WHERE anunt_lista_is_prioritar IS NOT NULL)
UNION
(SELECT anunt_lista_id
FROM anunturi__lista
WHERE anunt_lista_is_prioritar IS NULL)
ORDER BY (anunt_lista_is_prioritar IS NULL) ASC,
CASE WHEN anunt_lista_is_prioritar IS NOT NULL THEN
RAND()
ELSE anunt_lista_id END
LIMIT 100
The first clause of the order by: (anunt_lista_is_prioritar IS NULL) ASC is going to give false (0) when it isn't NULL and true (1) when it is NULL. Since it is ordering ASC, 0 will appear first than 1.
You can make dummy columns for order by!
Try this:
SELECT
if(anunt_lista_is_prioritar IS NOT NULL, rand() , 0) as fld_1,
if(anunt_lista_is_prioritar IS NULL,anunt_lista_id , 0) as fld_2,
anunt_lista_id
FROM anunturi__lista
order by fld_1 desc , fld_2 asc
Limit 100