When I select data from a MySQL table and order it by a DECIMAL column DESCENDING, this is the order:
3, 2, 1, -1, 0
Why is this so?
How to correctly set the order so that it is:
3, 2, 1, 0, -1 ?
EDIT
Actually, the problem is with NULL data. This is the order it does:
3, 2, 1, -1, NULL, NULL
This is the desired order:
3, 2, 1, NULL, NULL, -1
use COALESCE in your ORDER BY clause
SELECT *
FROM tableName
ORDER BY COALESCE(columnName, 0) DESC
SQLFiddle Demo
use the following syntax for that
ORDER BY column DESC
If you're ordering by a column with nulls, they always end up at the beginning or end of your results. Null means unknown, not zero.
If you want to treat them as zero you can use ifnull(column, 0) in your select statement.
Related
I'm trying to sort a query by given values like this:
ORDER BY FIELD(items.stock_id, 1, 5, NULL, 3, 6)
But it seems it doesn't work and null comes first or last depending on it being descending or not.
The order is not always the same hence [1,5,NULL,3,6] changes every time and is dynamic.
FIELD-function does not match the NULL-stock_id as NULL value (NULL does not have any value).
You could use a magic number:
ORDER BY FIELD(IFNULL(items.stock_id,-1), 1, 5, -1, 3, 6)
Is there a way to use SQL to sort a column by the first group of digits that appears in the column?
For example, the column contains values like so:
PPP-26-8
PPP-29-8
PPP-216-8
PPP-220
PPP-236
Only the first group of digits is to be considered for sorting in increasing numerical order, i.e. 26, 29, 216, 220, 236
I currently have something like this, which kind of works, but gives me warnings:
CAST(RIGHT(model, LENGTH(model) - 4) as UNSIGNED) ASC
Warning, specifically is this:
Warning | 1292 | Truncated incorrect INTEGER value: '216-8'
Update
It seems like this will do it, where - is the delimiter:
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(model, '-', 2), '-', -1) as UNSIGNED) ASC
You could use string function to get string after first - and * 1 for type casting
select *
from demo
order by substring_index(substring_index(col,'-',2),'-',-1) * 1
demo
Assuming you always mean the second group (as defined by the "-"), then you can use substring_index(). If they always begin with "P-", you can do:
order by length(substring_index(model, '-', 2)),
substring_index(model, '-', 2)
If the initial part can be of variable length, go fo:
order by substring_index(substring_index(model, '-', 2), '-', -1) + 0
The + 0 converts the value to a number, for ordering purposes. The use + 0 for conversion uses silent conversion in MySQL. That is, it does not generate an error when the string is non-numeric. Instead, it just treats such strings as a value of "0".
You can try this:
SELECT ...
FROM MyTable
ORDER BY SUBSTRING_INDEX(SUBSTRING_INDEX(model, '-', 2), '-', -1);
If you want this to use an index, you'll have to create a virtual column and an index on the virtual column (this works in MySQL 5.7 and later).
ALTER TABLE MyTable
ADD COLUMN model_second_number AS (SUBSTRING_INDEX(SUBSTRING_INDEX(model, '-', 2), '-', -1)+0),
ADD KEY (model_second_number);
Then you have an opportunity to sort by that index:
SELECT ...
FROM MyTable
ORDER BY model_second_number;
I Have a Table which has a Column of Type 'varchar' of size 255 char. The sample values look like this
Test/16-17/1
Test/16-17/2
test/16-17/10
Test/16-17/11
Test/16-17/20
Test/16-17/22
However on Using ORDER BY clause in the Select the Result is in following order
Test/16-17/1
Test/16-17/10
Test/16-17/11
Test/16-17/2
Test/16-17/20
Test/16-17/22
How Do I get the Result in the Chronolgical Order of Numerical Values in the End of the values?
If it follows the same / and have 2 digits in the column, you can use
order by right(vtest,2)
ORDER BY CONVERT( RIGHT( test_column_name,
LENGTH(test_column_name) - LOCATE('/', REVERSE(test_column_name))
), UNSIGNED INTEGER);
OR
ORDER BY CONVERT(substring_index(id, '/', -1), UNSIGNED INTEGER);
For your particular examples, you can order by length and then the value:
order by length(vtest), vtest
I don't know if this will work for other rows not in the question.
This will work no matter what the first 10 characters are:
ORDER BY CONCAT(LEFT(vtest, 10), CASE WHEN LENGTH(vtest) = 12
THEN CONCAT(0,RIGHT(vtest,1))
ELSE RIGHT(vtest,2) END)
Select the end part after the last "/", and then multiply it by 1 to convert it to a number:
ORDER BY RIGHT(test_column, LENGTH(test_column) - LOCATE('/', REVERSE(test_column))) * 1;
OR
ORDER BY substring_index(id, '/', -1) * 1;
This is basically the same as the answer by Keyur Panchal, but it uses implicit conversion which has several advantages: 1) Easier to read/write, 2) You don't need to worry about the type to convert to, 3) It ignores characters if they happen to exist in some values.
I need to make a column that counts the amount of variables which are above 0, and that won't return null if there is any non-null value in it, for each value in an id column.
What I managed to make is using a sum between some boolean operations:
IF 'A' THEN 'B' ELSE 'C' (at least that's what I've got)
select ID, `jul`, `aug`, `set`, `oct`, `nov`, `dec`,
((((not `jul`) or 1) and (`jul` or 0))
+(((not `aug`) or 1) and (`aug` or 0))
+(((not `set`) or 1) and (`set` or 0))
+(((not `out`) or 1) and (`out` or 0))
+(((not `nov`) or 1) and (`nov` or 0))
+(((not `dec`) or 1) and (`dec` or 0))) as sum from table;
It works at first view, but if there is any null value in a line, the sum returns null for each respective id.
What could I do to avoid this problem?
try
SUM( IFNULL(jul,0)+IFNULL(ago,2) ) as sum from table
/*
obs: the SUM is good to sum multiple values
IFNULL returns 0 to the sum if jul is null and 2 for ago if ago is null in the example.
*/
i think it works. :)
You need to use a coalesce or variant to deal with nulls. Null value represents an unknown. You can't add unknowns and get something other than an unknown.
NULL + 1 = NULL
COALESCE(NULL, 0) + 1 = 1
Use isnull(columnname, 0) to turn nulls into 0s. So isnull('jul',0)+isnull('aug',0) etc.
SELECT *, IFNULL(parent, id) AS p, IFNULL(reply_comment_id, id) AS r
FROM article_comments ORDER BY p ASC, r ASC, date DESC
I want use LIMIT. If I have more row, I want limit the query by "p".
In image: ("p": 1, 1, 1, 1, 1) – this is ONE, ("p": 2, 2, 2, 2, 2, 2, 2) – this is TWO...
For example, I want: if I use LIMIT 1, then only show ("p": 1, 1, 1, 1, 1).
Here is the query I would use:
SELECT * FROM
FROM article_comments
WHERE id = 1 OR parent = 1
ORDER BY parent ASC, reply_comment_id ASC, `date` DESC
Note that I see no need for your calculated columns here. When ordering by parent and reply_comment_id in ascending fashion, the NULL values will be first in sort.
Make sure you have indexes on parent, reply_comment_id, and date fields (in addition to id, which I assume is primary key)
Also, you might want to consider using a datetime field for your date column, rather than unix timestamp. It is much user friendly when viewing the data in the database, as well as when trying to query date ranges/ So can write your filter like this:
WHERE `date` BETWEEN '2012-01-01 00:00:00' AND '2012-12-31 23:59:59'
Instead of having to due timestamp conversions.