MySQL Order by Date, with NULL first - mysql

I have a select statement that I would like to select 1 record from a table. The structure is:
id | start_time
--------------
1 NULL
2 2014-08-23
3 2014-09-01
I would like to select the item with a NULL start time, but if that does not exist I would like it to select the latest start_time. I have tried using ORDER with LIMIT 1, but using ORDER BY start_time either gives NULL first followed by the earliest starting, or latest starting then NULL. Is it possible to have result order 1,3,2 ?

You can use two sort expressions to get the ordering you want:
select t.*
from table t
order by (start_time is null) desc,
start_time desc
limit 1;

You can have two different ORDER BY expressions:
SELECT * from table ORDER BY (start_time IS NULL) DESC, start_time DESC;

Related

MySQL ORDER BY CASE Date ASC/DESC

I have these records on my table:
ID Win Date
1 NULL 2019-01-15
2 12 2019-01-10
3 NULL 2019-01-12
4 513 2019-01-14
I want the order to be:
win that are null first, ordered by date asc and win that are not null after, ordered by date desc
So the order would be: 3, 1, 4, 2
How can i achieve this using order by case or any other way?
You should use ORDER BY CASE ... here:
SELECT * FROM ...
ORDER BY
NOT ISNULL(Win),
CASE
WHEN Win IS NULL
THEN `Date`
ELSE DATEDIFF('9999-01-01', `Date`)
END
This should with for dates before 9999-01-01. Adjust this value if you'd have latter dates.
Try this
order by iif(win is null,1,0) DESC, Date DESC
Sorry misread the intended order try something like this
Order by iif(win is null,1,0) DESC,DateDiff(Day,'1900-01-01',Date) * iif(win is null,1,-1) DESC
the idea is to get a value that you can make negative by using an if statement

How to select records from mysql along with one previous record

I have table like this
+----+----------------------+------------+
| id | desc | date |
+----+----------------------+------------+
| 15 | nah_i_kid | 2017-06-07 |
+----+----------------------+------------+
| 17 | it_is_just_the_cat | 2017-06-08 |
+----+----------------------+------------+
| 18 | thank_God | 2017-06-09 |
+----+----------------------+------------+
| 44 | no_kidding | 2017-06-10 |
+----+----------------------+------------+
My sql is
SELECT * FROM TABLE WHERE date between '2017-06-09' AND '2017-06-12'
I want the result should contain one previous record also (i-e record having id=17 take it example)
Thanks.
If you are using MYSQL, I have tried and it work good.
(select * from table where date < '2017-06-09' order by date desc limit 1 ) union (select * from table where date between '2017-06-09' AND '2017-06-12' order by date)
If you want the records from the previous date, you can do:
select t.*
from t
where date > (select max(t2.date) from t t2 where t2.date < '2017-06-09') and
date <= '2017-06-12';
This does what you want, assuming you have no duplicates on a date.
If you want exactly one row and you know the ids are assigned in chronological order, you can do:
select t.*
from t
where id > (select max(t2.id) from t t2 where t2.date < '2017-06-09') and
date <= '2017-06-12';
This solves the problem by taking the most recent previous record based on id.
If the ids are not in chronological order and you can have duplicates, the query gets more difficult. There is no definition of the "previous record". A union all is the best solution:
(select t.*
from t
where date < '2017-06-09'
order by date desc
limit 1
) union all
select t.*
from t
where date > >= '2017-06-09' and
date <= '2017-06-12'
I think this is what you're looking for.
The first part of the query is identical to yours, the second part gets all the values before your first date 2017-06-09, orders the values by date DESC, then limits the query to only take the topmost value using LIMIT 1.
SELECT
*
FROM table
WHERE `date` BETWEEN '2017-06-09' AND '2017-06-12'
OR `id` = (
SELECT
`id`
FROM table
WHERE `date` < '2017-06-09'
ORDER BY `date` DESC
LIMIT 1
)
I want the result should contain one previous record also (i-e record having id=17 take it example)
If you know that the rows are created in chronological order, and your id field is auto-increment, then you don't even need to use the date field, because you can assume that a higher id indicates a later record. So just cap your search on the id you want, and grab two rows:
SELECT * FROM TABLE WHERE id <= 17 ORDER BY id DESC LIMIT 2;
This has the added benefit of being fully indexed, which may not be the case if you introduce a WHERE clause on the date field.

Order by date but add important at first in MySQL

I've a table what looks like that:
ID | title | author | timestamp | livetime | special
My goal is select all from table where livetime is larger than current timestamp and order it by timestamp desc BUT records where "special" is true must be in first (of course, also ordered). It's possible to do only with the MySQL?
My SQL Query looks that:
SELECT * FROM ads WHERE livetime > UNIX_TIMESTAMP() ORDER BY timestamp DESC
Yes, you can sort by two columns. Value of true is 1 and false 0, so you need to sort in the descending order.
SELECT * FROM ads WHERE livetime > UNIX_TIMESTAMP() ORDER BY special DESC, timestamp DESC
SELECT * FROM ads
WHERE livetime > UNIX_TIMESTAMP()
ORDER BY special <> 1,
timestamp DESC
Try this.
SELECT * FROM ads WHERE livetime > UNIX_TIMESTAMP() ORDER BY special, timestamp DESC

mysql order by timestamp latest and group the rows of that category with limit

Order by timestamp DESC and group by a category with a limit in Mysql
cat timestamp
----------------
11 1308748405
11 1308747228
13 1308749273
57 1308748289
11 1308746228
...to get a table of the format, where it is sorted by timestamp and also relevant rows of that category grouped together with a limit. (ie group by category of all rows and arrange amoung the groups by the descending order of timestamps but keep the group together)
cat timestamp
----------------
13 1308749273
11 1308748405
11 1308747228
57 1308748389
I am guessing what you are looking for is: Get the minimum timestamp per category, and sort the results by timestamp?
SELECT t.cat, t.timestamp
FROM table t
JOIN (SELECT MIN(timestamp) as min_time, cat
FROM table
GROUP BY cat) as tmp
ON (t.cat = tmp.cat AND t.timestamp = tmp.min_time)
ORDER BY 2 DESC
SELECT cat, timestamp
FROM yourtable
ORDER BY timestamp DESC
GROUP BY cat
LIMIT 4
without more details, this is the best you're going to get.
If you want to get 4 groups based on sorted by it's latest timestamp. This may works:
SELECT tblTes.cat, tblTes.timestamp
FROM tblTes INNER JOIN (SELECT cat, MAX(TIMESTAMP) AS latest FROM tblTes GROUP BY cat) AS subQuery
ON tblTes.cat = subQuery.cat AND tblTes.timestamp = subQuery.latest
ORDER BY tblTes.timestamp DESC LIMIT 4;

MySQL getting MAX of previous WHERE condition

I have a table:
id | score | date
bob | 40 | 2010-1-1
bob | 70 | 2010-1-15
sue | 55 | 2010-1-1
sue | 80 | 2010-2-1
I want to query for either the score for a user on a specific date OR, if no score exists for that user on that date,return the score from the most recent date for that user.
Is there a way to do this without a sub-query?
For instance, if I do:
SELECT score
FROM table
WHERE id = '$id'
AND IFNULL(
date = DATE(FROM_UNIXTIME($date)),
MAX(date)
)
I would get no result, as the id does not show up for the most recent date.
Update
Felix reminded me I can't use aggregate functions in the WHERE clause, so now I'm wondering if there is a pseudo-aggregate date function for saying "most recent date" in the where clause, and if so, if I can specify the user when using THAT function?
Update 2
So this is what I have gotten to work, but I still don't know if it's the best way to go (ie, do I need the nested query?):
SELECT score
FROM table
WHERE id = '$id'
AND date = IFNULL(
(SELECT date FROM table
WHERE id = '$id' AND
date = DATE(FROM_UNIXTIME($date))
),
(SELECT MAX(date) FROM table
WHERE id = '$id'
)
)
Not sure of the performance of this one:
SELECT a.*
FROM table a
LEFT JOIN table b ON (
b.date=DATE(FROM_UNIXTIME($date)) AND b.date=a.date AND b.id=a.id
)
WHERE a.id='$id'
ORDER BY b.date DESC, a.date DESC
LIMIT 1
SELECT score
FROM table
WHERE id = '$id'
AND date > '2010-01-01'
ORDER BY date DESC
LIMIT 1
EDIT
See my second comment regarding the interpretations:
Interpretation 1:
SELECT score
FROM table
WHERE id = '$id'
AND date >= '2010-01-01'
ORDER BY date ASC
LIMIT 1
Interpretation 2:
SELECT score,
LEAST(ABS(DATEDIFF('2010-01-01', date)), 1) AS myorder
FROM table
WHERE id = '$id'
AND date >= '2010-01-01'
ORDER BY myorder ASC, date DESC
LIMIT 1
Use this query :
SELECT * FROM test
WHERE date = (
SELECT MAX(date) FROM test
) ;
If you want based on the id , you need to do group by operation on id column