Testing for NULL in ORDER BY - mysql

In database; there's 3 columns, Name, CreatedDate and UpdatedDate.
I want to make stored procedure to to get all rows order last update or created date.
Here's my sample code.
SELECT * FROM tbl_name
ORDER BY CASE WHEN UpdatedDate != null THEN UpdatedDate ELSE CreatedDate END desc
But received wrong result. Any Idea?

When comparing with null you need the is operator.
SELECT * FROM tbl_name
ORDER BY CASE WHEN UpdatedDate is not null
THEN UpdatedDate
ELSE CreatedDate
END desc
or in your case you can just use
SELECT *
FROM tbl_name
ORDER BY coalesce(UpdatedDate, CreatedDate) desc

Related

How to delete older rows with same ID and different timestamp in MySQL?

I have a mysql table, simplified version below:
ID Col1 Col2 CreatedDate
232 my data some data 2017-10-15 8:50:20
232 my data some data 2017-10-14 8:52:20
232 my data some data 2017-10-13 8:53:20
232 my data some data 2017-10-12 8:55:20
232 my data some data 2017-10-11 8:54:20
ID is int and CreatedDate is datetime
I want to keep the most recent two rows and delete all other with the same id. I will get ID from old.ID in the trigger (e.g., where ID=old.ID ).
Any help?
In My sql there is no option to using LIMIT in subquery, so you need to create as below:
delete from table_name
where
CreatedDate not in
(select CreatedDate from
(select * from
table_name
where id='232' order by CreatedDate desc limit 2) as t);
This code will delete everything except the last two record of the ID old.ID of your trigger.
DELETE FROM `mytable`
WHERE ID = old.ID AND CreatedDate not IN ( -- Delete rows ID = old.ID but not in the subquery
SELECT CreatedDate
FROM (
SELECT CreatedDate -- This select the last 2 from old.ID
FROM `mytable`
WHERE ID = old.ID
ORDER BY CreatedDate DESC
LIMIT 2 -- keep last two record
) foo
)
This will keep the most two recent data of every id.
DELETE FROM `mytable` WHERE ID and CreatedDate NOT IN(
SELECT CreatedDate
FROM (
SELECT max(CreatedDate) AS CreatedDate,
max(ID) AS ID FROM mytable GROUP BY ID
UNION
SELECT max(CreatedDate), max(ID)
FROM mytable
WHERE CreatedDate not in
(
SELECT max(CreatedDate) as CreatedDate
FROM mytable GROUP BY ID
) GROUP BY ID
) foo
)
Here you can use this query ,
delete from table Where CreatedDate not in (
SELECT CreatedDate FROM table order by CreatedDate Desc limit 2 )
If it shows error of version then you can go with ,
delete from table WHERE CreatedDate not in
(
SELECT * FROM (
SELECT CreatedDate FROM table order by CreatedDate Desc limit 2
)
as t);

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

MySQL: Get rows with creation date string newer than given date string

I am trying to create a prepared statement with following code:
$statement = $db->prepare("SELECT * FROM myTable WHERE
STR_CMP(creationDate, $startingDate) = 1 ORDER BY creationDate DESC ");
I have also tried this:
$statement = $db->prepare("SELECT * FROM myTable WHERE
(creationDate > $startingDate) = 1 ORDER BY creationDate DESC ");
But I am getting null $statement. My goal is to get rows which it's creatrion date is newer than given date string. My creationDate column is stored as string.
I have logged my query string and it look like:
SELECT * FROM myTable WHERE (creationDate > 05.02.2015 14:08:31) = 1 ORDER BY creationDate DESC
What am I doing wrong?
1) You have to compare date to date.
SELECT * FROM myTable WHERE
DATE_FORMAT(STR_TO_DATE(creationDate, '%d.%m.%Y %H:%i:%s'),'%d.%m.%Y %H:%i:%s')
> '.$startingDate.' ORDER BY creationDate DESC
Tips
2) Store date in DB as date not string
3) Your date string seems to invalid?
Why not YYYYMMDD.
ORDER BY creationDate DESC may implict unexpected reulsts
I have solved my problem by trying my query string in my phpMyAdmin sql query section of my database. And I have relized when I build my query like this:
$statement = $db->prepare("SELECT * FROM myTable WHERE
(creationDate > $startingDate) = 1 ORDER BY creationDate DESC ");
It becomes:
SELECT * FROM myTable WHERE (creationDate > 05.02.2015 14:08:31) = 1
ORDER BY creationDate DESC
and MySql gives error for 05.02.2015 14:08:31
So I have prepared my statement like this:
$queryString = 'SELECT * FROM arendi_ideas WHERE (creationDate > "'.$startingDate.'") = 1 ORDER BY creationDate DESC';
$this->logger->debug("GetIdeasNewerThan: Query string = $queryString");
$this->statement = $this->db->prepare($queryString);
and it works fine.

Sorting a column in ascending and descending order depending on the current date

Please help. Here my mySQL query
SELECT *
FROM (`products`)
ORDER BY (
CASE WHEN `ExpiredDate` > NOW()
THEN 1
ELSE 0
END) DESC , `ExpiredDate` ASC
I'm going to sort the array result as the available products like this:
12-10-2013
12-15-2013
12-28-2013
12-09-2013 -- Today
12-08-2013
12-04-2013
12-01-2013
But the current result is now the expired products is order by ascending like this:
12-10-2013
12-15-2013
12-28-2013
12-09-2013 -- Today
12-01-2013
12-04-2013
12-08-2013
This should do the trick:
SELECT * FROM products
ORDER BY ExpiredDate < NOW(), ABS(TIMESTAMPDIFF(SECOND, expiredDate, NOW()))
Fiddle here
You should use following query instead of yours,
SELECT *
FROM (products)
ORDER BY (
CASE WHEN DATE_FORMAT(ExpiredDate,'%Y-%m-%d') > NOW()
THEN 1
ELSE 0
END) DESC , ExpiredDate ASC
More details can be found at
http://www.mysqltutorial.org/mysql-date_format/

MySQL Orderby a number, Nulls last

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