PHP, MYSQL: Order by date but empty dates last not first - php

I fetch an array with todo titles and due dates from MySQL. I want to order it by date and have the oldest on top. But there are some todos without a date. These todos I don't want to show at first positions but rather at the bottom of my list. Unfortunately MySQL put the empty ones first.
Is there any way I can do it in one query (can't use MySQLi, using CI's ActiveRecord). I could run a second query for all todos without dates and put them at the bottom. But I'd like to make it in one query – if possible?

You can do it in MySQL with the ORDER BY clause. Sort by NULL first, then the date.
SELECT * FROM your_table ORDER BY (date_column IS NULL), date_column ASC
Note: This assumes rows without a date are NULL.

Yes
SELECT *
FROM table
ORDER BY CASE your_date
WHEN '' THEN 'b'
ELSE 'a'
END,
date ASC

possibly add a NVL( thedate, to_date('2099-12-31','yyyy-mm-dd')) in the order by clause

You can use this:
select * from my_table
order by if(isnull(my_field),1,0),my_field;

Well, as a pure MySQL answer, I would probably do it like this.
select todo.title, todo.due_date
from todo
order by ifnull(todo.due_date, '9999-12-31')

Related

Parse SQL results by month using timestamp MySQL

I have a small problem with SQL. I need to select ID of rows and group them into arrays (or something) BY MONTH? I have a timestamp column there.
So if there are rows like this:
ID Timestamp
1 blalba(1.10.2017)
2 blabla(2.10.2017)
3 blabla(1.5.1996)
The output would be like
array(
[5.1996] => array([3]),
[10.2017] => array([1,2]);
)
(Or something like this).
Is this possible in PHP using some PHP libraries? Or Do I have to implement my own class doing this?
You are probably looking for group_concat
select group_concat(id separator ', ') as myList,
DATE_FORMAT(Timestamp, '%Y-%m') from <YOUR_TABLE>
GROUP BY DATE_FORMAT(Timestamp, '%Y-%m');
Well you might be handle this on the MySQL side by ordering by month/year:
SELECT
ID, Timestamp
FROM yourTable
ORDER BY
DATE_FORMAT(Timestamp, '%Y-%m');
This query would return a result set to PHP which would be ordered such that all records in the same month and year would be clustered together. You could then just iterate this result set and process the records as you want.

Get first/last value from SQL selection using PHP

I have a SQL query in my php file (I use this file to calculate graphic timeblocks based on starting time and duration of an event; starttime and duration are my columns in SQL table).
How can I print/get last or first value from selection below using php? I mean first or last value from column 'starttime' to be precise.
$query1=mysqli_query($db,"select * from LISTS where category='planner'
order by date,timestart asc");
I googled since I am very much beginner but results did not make much sense because I don't have much skills yet. Therefore I am asking you.
Thanks in advance. Also can you please explain in very primitive way, some terms I might not understand at this point.
If you wan't both the first and last value in one MySql state you can use "Union". The UNION operator is used to combine the result-set of two or more SELECT statements.
To get either first or last value use "limit" and set this to 1, then order by asc or desc.
Example:
select * from LISTS where category='planner' order by date,timestart asc
limit 1) union (select * from LISTS where category='planner' order by
date, timestart desc limit 1
So I decided to find only first value based on my selection. I had to show it on the page, this is what worked for me.
$query3=mysqli_query($db,"select datetime from LISTS where
category='planner' order by date,timestart asc");
$SelectionArray=mysqli_fetch_array($query3);
$FIRSTdatetime=reset($SelectionArray);
echo $FIRSTdatetime;

How to ASC DESC Date which data type is varchar

How do can I asc date?
I have the folllowing in sql
2014-3-18
2014-1-15
2014-3-20
2015-3-18
I tried the ff codes but it just gives me error in my db.
And yes the data type of the column is varchar.
And also there's NULL values in that column.
SELECT *
FROM `locate`
ORDER BY
CONVERT(DateTime, `Date`,101) DESC
Please help. Thanks! :)
Looks like you use mysql so you can not use the mssql convert function. you have to use STR_TO_DATE
SELECT *
FROM `locate`
ORDER BY
STR_TO_DATE(`Date`,'%Y-%m-%d') DESC
For more Information see the documentation
I'm guessing EventDate is a char or varchar and not a date otherwise your order by clause would be fine.
You can use CONVERT to change the values to a date and sort by that
SELECT *
FROM
vw_view
ORDER BY
CONVERT(DateTime, EventDate,101) DESC
The problem with that is, as Sparky points out in the comments, if EventDate has a value that can't be converted to a date the query won't execute.
This means you should either exclude the bad rows or let the bad rows go to the bottom of the results
To exclude the bad rows just add WHERE IsDate(EventDate) = 1
To let let the bad dates go to the bottom you need to use CASE
e.g.
ORDER BY
CASE
WHEN IsDate(EventDate) = 1 THEN CONVERT(DateTime, EventDate,101)
ELSE null
END DESC
Use the order by this way :
SELECT DATE_FORMAT(`date`, '%d-%m-%Y') as date_formatted
FROM locate
ORDER BY `datetime` DESC
Please let me know if it works.

How to sort rows by ON, OFF, SOLD

I have followings 3 values that could be in a row in database - ON, OFF, SOLD (column sort_it). When I set the sort clausule on ORDER BY sort_it ASC, so I will get the items with a value in the sort_in column OF, then ON and SOLD.
But I need the sequence ON, OFF, SOLD.
Exist any way to do it somehow? I mean... edit a way saving data into database will be demanding, so I would do this in the last moment.
Yes you can use custom data sortings like this:
SELECT * FROM table ORDER BY FIELD(`sort_it`,'ON','OFF','SOLD'),`sort_it`
You can use a CASE statement to generate your custom ordering sequence from the underlying values, something like this:
ORDER BY
CASE sort_it
WHEN 'ON' then 1
WHEN 'OFF' then 2
WHEN 'SOLD' then 3
END
Sample Demo: http://sqlize.com/MGz6lLb0Qk
Using Strings is generally a bad idea. it would be better to use a numeric type. Then you can say ON=1, OFF=2 and SOLD=3 and then sort.
SELECT t.*, IF(sort_it='ON',1,IF(sort_it='OFF',2,3)) as new_sort FROM Table AS t ORDER by new_sort ASC
Another solution from comments on MySql manual:
http://dev.mysql.com/doc/refman/5.0/en/sorting-rows.html
select * from tablename order by priority='High' DESC, priority='Medium' DESC, priority='Low" DESC;

Getting the result of a MySql query order by date when the date field can contain strings differents than dates

I have a date field on my Sql table that is actually a text field, thats because there sometimes I save dates like 10/28/2011 and sometimes strings like present.
It is possible without touching the table structure, and maybe just with the sql query having the result correct organanized by date? Where present is the max value and then the dates in decreasing order.
If you really can't sort the data type out on those string date columns then this might help:
select t.*,
case when date_end = 'present' then curdate()
else convert(concat(substr(date_end,7,4),'-',substr(date_end,1,2),'-' ,substr(date_end,4,2)),date) end as "realDate"
from myTable t
order by "realDate" desc;
Right. I'm off to go and say 100 Hail Marys to the MySQL database god now. Ugh.
Best way would be :
fix the db and add proper date fields (add proper date or datetime field and update values from text fields and format them to be dates on the fly)
keep your present status in a text field and you can use that as a extra condition
I know you asked for a way to sort it correctly as a text column, but I really don't think that's the right way to this.
I agree with #stivlo. It is very easy to update the database to deal with this is a better way. You can either:
Convert the column to a real date, and use NULL to represent "present" instead of the string "present".
Or, if you need NULL reserved for some other meaning, you can convert the column to a real date, and add additional boolean flag columns to specify when the dates are "present".
Either way, you should definitely convert those text fields to real dates.
select job_desc, data_begin, data_end from table where data_end = 'present'
union
select job_desc, data_begin, cast(data_end as date) data_end from table where data_end <> 'present' order by data_end desc
Not sure if syntax is completely correct, so you might want to check the mySql 'union' syntax
Another solution might be using coalesce for 'present':
select cast(coalesce(data_end,now()) as date) data_end from table order by data_end desc
this way the column gets interpreted as dates and 'present' gets replaced with the present date

Categories