Order by multiple columns with multiple conditions - mysql

I have a table with some events like this
id----------title-----------date-------------status
1-----------birthday-------2018-03-12--------1
2-----------match----------2018-03-13--------2
3-----------anniversary----2018-03-10--------1
4-----------trip-----------2018-03-15--------1
5-----------birthday-------2018-03-17--------2
6-----------birthday-------2018-03-11--------1
Expected Result
id----------title-----------date-------------status
1-----------birthday-------2018-03-12--------1
4-----------trip-----------2018-03-15--------1
5-----------birthday-------2018-03-17--------2
2-----------match----------2018-03-13--------2
6-----------birthday-------2018-03-11--------1
3-----------anniversary----2018-03-10--------1
I need to query it like the first rows which have dates greater than today with status 1 should appear first and then the rest in desc.
Suppose today is 2018-03-11 then row with id 1 should appear first and then the rest of the rows is desc order
This is what I have tried so far
SELECT *
FROM events
ORDER BY (date > CURDATE() and status = 1) asc,
date desc

You can use multiple keys in an order by:
order by (date >= curdate() and status = 1) desc,
date desc

I believe your SQL should be something like this but is hard to say without expected results.
Query
SELECT
*
FROM
[table]
WHERE
date > CURDATE()
AND
status = 1
ORDER BY
date ASC
LIMIT 1
UNION
SELECT
*
FROM
[table]
WHERE
id NOT IN (
SELECT
id
FROM
[table]
WHERE
date > CURDATE()
AND
status = 1
LIMIT 1
)
AND
date > CURDATE()
ORDER BY
date DESC

Related

SQL retrieve all rows between two dates and a specific number of rows before the date ordered by date

As the title says, I have a table with a date column. I am trying to retrieve all rows between 2 dates as well as X number of rows before the beginning date ordered by date.
Take a select * from table order by date DSC
20200201
20200101
20191201
20191101
20191001
20190901
20190801
20190701
I want between 20200201 and 20191201 and the previous 3 rows(not knowing the date)
result
20200201
20200101
20191201
20191101
20191001
20190901
my current query returns a random set of high dates between the union for some reason:
(SELECT * FROM Table WHERE Date BETWEEN 20200201 AND 20191201 ORDER BY Date ASC)
UNION
(SELECT * FROM Table WHERE Date < 20191201 ORDER BY Date DESC LIMIT 3)
Any idea where I am going wrong?
One method uses lead():
select t.*
from (select t.*,
lead(date, 3) over (order by date) as next_date_3
from t
) t
where (date < '202o-02-01' and (next_date_3 >= '2020-02-01' or next_date_3 is null) ) or
(date between '2020-02-01' and '2019-12-01')
I tried this query and it worked for me:
(SELECT * FROM Table WHERE Date BETWEEN 20191201 AND 20200201 ORDER BY Date ASC)
UNION
(SELECT * FROM Table WHERE Date < 20191201 ORDER BY Date DESC LIMIT 3)
The first select shows me:
20191201
20200101
20200201
The second select shows me:
20191101
20191001
20190901
The issue was as jarlh pointed out, the order of the subquery's were not kept(thats why things were jumbled) and a simple ORDER BY of the whole UNION fixed this. I did not try Gordon's response as this solved my issue so:
(SELECT * FROM Table WHERE Date BETWEEN 20191201 AND 20200201)
UNION
(SELECT * FROM Table WHERE Date < 20191201 ORDER BY Date DESC LIMIT 3)
ORDER BY Date ASC
Thank you

How to query SQL on date AND time

My current table looks like this - Table is called "S"
DJ DATE
---- ------
test yyyy/mm/dd hh:mm:ss
I've worked up to the below SQL query
SELECT *
FROM `S`
WHERE `DATE` = '2017-02-27 17:00:00'
ORDER BY `S`.`DATE` DESC
LIMIT 0 , 1
Rather than having the set date and time though I would like to query based on the current date AND time. I'm using datetime type structure.
All I'm looking to do is query the current datetime to get the current name from the DJ row
Thanks!
You can use now() function to get the current datetime.
SELECT *
FROM `S`
WHERE `DATE` = now()
ORDER BY `S`.`DATE` DESC
LIMIT 0 , 1
If you want to get result for today's date, you can use curdate and date function
SELECT *
FROM `S`
WHERE date(`DATE`) = curdate()
ORDER BY `S`.`DATE` DESC
LIMIT 0 , 1
With mysql, you can use the CURRENT_TIMESTAMP() function.
SELECT *
FROM S
WHERE DATE = CURRENT_TIMESTAMP()
ORDER BY S.DATE DESC
LIMIT 0, 1
I think you want:
select s.*
from s
where date(date) = CURDATE() and
hour(date) = hour(NOW())
order s.date` DESC
limit 0, 1;

MySQL Select where column greater than or equal to closest past date from given date

TABLE
Table:
Id Date
1 01-10-15
2 01-01-16
3 01-03-16
4 01-06-16
5 01-08-16
Given two dates startdate 01-02-16 and enddate 01-05-16. I need to get the data from the table such that it returns all data between the closest past date from startdate and closest future date from enddate including the two dates. So the result will look like this.
Result:
Id Date
2 01-01-16
3 01-03-16
4 01-06-16
What I am doing
What I am doing now is fetching the whole data and removing from the array results less than closest fromdate and greater than closest enddate
What I want
What I want is to do this in query itself so that I don't have to fetch the whole data from table each time.
If you column's type is date, use union can do it:
(select * from yourtable where `date` <= '2016-01-02' order by `date` desc limit 1)
-- This query will get record which is closest past date from startdate
union
(select * from yourtable where `date` => '2016-01-05' order by `date` asc limit 1)
-- This query will get record which is closest future date from enddate
union
(select * from yourtable where `date` between '2016-01-02' and '2016-01-05')
Demo Here
Imaging your date is in YYYY-mm-dd
## get rows within the dates
SELECT * FROM tab WHERE ymd BETWEEN :start_date AND :end_date
## get one row closest to start date
UNION
SELECT * FROM tab WHERE ymd < :start_date ORDER BY ymd DESC LIMIT 1
## get one row closest to end date
UNION
SELECT * FROM tab WHERE ymd > :end_date ORDER BY ymd LIMIT 1
Try this
Select *
From
dTable
Where
[Date]
Between
(Select
Max(t1.Date)
From
dTable t1
Where
t1.date <startdate) And
(Select
Min(t2.Date)
From
dTable t2
Where
t2.date >enddate)
If Date is String, STR_TO_DATE and DATEDIFF can be used here.
SELECT id, Date
FROM tab
where
STR_TO_DATE(Date, '%d-%m-%y') BETWEEN('2016-02-01')AND('2016-05-01')
or
id = (SELECT id FROM tab
where STR_TO_DATE(Date, '%d-%m-%y') > '2016-05-01'
ORDER BY DATEDIFF(STR_TO_DATE(Date, '%d-%m-%y'), '2016-05-01') Limit 1)
or
id = (SELECT id FROM tab
where STR_TO_DATE(Date, '%d-%m-%y') < '2016-02-01'
ORDER BY DATEDIFF('2016-02-01', STR_TO_DATE(Date, '%d-%m-%y')) Limit 1)

Mysql query latest before date or (if empty then) first after

I'm trying to retrieve an entry with the latest date before a given date, and if it doesn't exist then take the soonest after that given date.
I tried googling it, but I couldn't find this scenario
You can do this with order by and limit:
select t.*
from table t
order by (datecol < #date) desc,
(case when datecol < #date then datecol end) desc,
datecol asc
limit 1;
for latest before given date -
select * from table where date_column<given_date order by date_column desc limit 1
now check the result if no row return then execute following query for soonest after given date -
select * from table where date_column>given_date order by date_column limit 1

SELECT records MySQL: between date + 1

Say I want to SELECT all records between two dates plus one record before and one record after that date? All records are ordered by date.
You could use a union combined with the limit statement. Something like what's below (untested, don't have access to mysql).
(select column from table where datefield > startdate and datefield < stopdate)
union
(select column from table where datefield < startdate order by datefield desc limit 1)
union
(select column from table where datefield > stopdate order by datefield limit 1)
This will give you the next row regardless of where it falls date-wise.
Thanks for syntax fix, ponies.
(select * from t where date < start_date order by date desc limit 1)
union (select * FROM t WHERE date between start_date and end_date)
union (select * from t where date > end_date order by date asc limit 1)
You can use functions to add or subtract values, like this:
select * from table where field1 < ADDDATE( CURTIME() , INTERVAL 1 DAY)
Check this link where there are some examples.
SELECT *
FROM table
WHERE date BETWEEN DATE_ADD(current_date(), INTERAL -1 DAY)
AND DATE_ADD(current_date(), INTERVAL 1 DAY);