How to get status between two dates in mysql database? - mysql

I have a query like this to get status without adding fields.
SELECT * ,
IF(DATEDIFF(STR_TO_DATE(end_date, "%Y-%m-%d"), CURDATE())<=0,"End","Running") status
FROM agreements
the query is running but I want to add status if the end date is less than 3 days then the status will show "will be ended"
so there will be 3 statuses in the query, END, RUNNING, Will be END

You can use CASE ..WHEN statements; also your STR_TO_DATE(end, '%Y-%m-%d') usage is unnecessary because DATEDIFF() function considers date part only for the calculation:
SELECT * ,
CASE WHEN DATEDIFF(end_date, CURDATE()) <= 0 THEN 'End'
WHEN DATEDIFF(end_date, CURDATE()) < 3 THEN 'Will Be End'
ELSE 'Running'
END status
FROM agreements

Related

MySQL Query Group By Date (12 hours Interval)

I wrote a sql query for getting number of users created in a period of time for plotting graph (grafana or chart js) , and my sql query is
SELECT
date(user.created_date) as "time",
count(distinct user.id) as Number Of User,
status as status
FROM user
WHERE
created_date >= FROM_UNIXTIME(1649635200) AND
created_date < FROM_UNIXTIME(1649894399)
GROUP BY user.status, date(user.created_date)
ORDER BY date(user.created_date)
Here in this query created date is passed dynamically from front-end,
Now i am getting the result like,
Now whenever i select the date filter from last 24 hours/12 hours some of the result is not there,
Is there is any way to modify my sql query to group by created_date with 12 hour interval
For Example, Now query result is 11/04/2022 - 5 Users(Application Created) I want query result like this 11/04/2022 00:00:00 2 - 2 users created 11/04/2022 12:00:00 - 3 users created
In grafana there is a filed $__timeFrom() and $__timeTo()
On the basis of this I rewrite my query:
SELECT
(CASE
WHEN HOUR(TIMEDIFF($__timeFrom(), $__timeTo())) <= 24
THEN user.created_date
ELSE date(user.created_date) end) AS "time",
count(distinct user.id) as Users,
FROM user
WHERE
user.created_date >= $__timeFrom() AND
user.created_date < $__timeTo() AND
GROUP BY CASE
when HOUR(TIMEDIFF($__timeFrom(), $__timeTo())) <= 24
then user.created_date
else date(created_date) end
ORDER BY CASE
when HOUR(TIMEDIFF($__timeFrom(), $__timeTo())) <= 24
then user.created_date
else date(created_date) end;
If you use this expresion in your GROUP BY, you'll get a 12-hour grouping.
DATE(created_date) + INTERVAL (HOUR(created_date) - HOUR(created_date) MOD 12) HOUR
You can, if you have the priv, declare a stored function to make this easier to read.
DELIMITER $$
DROP FUNCTION IF EXISTS TRUNC_HALFDAY$$
CREATE
FUNCTION TRUNC_HALFDAY(datestamp DATETIME)
RETURNS DATETIME DETERMINISTIC NO SQL
COMMENT 'truncate to 12 hour boundary. Returns the nearest
preceding half-day (noon, or midnight)'
RETURN DATE(datestamp) +
INTERVAL (HOUR(datestamp) -
HOUR(datestamp) MOD 12) HOUR$$
DELIMITER ;
Then you can do
SELECT
TRUNC_HALFDAY(user.created_date) as "time",
count(distinct user.id) as Number Of User,
status as status
FROM user
WHERE
created_date >= whatever AND
created_date < whatever
GROUP BY user.status, TRUNC_HALFDAY(user.created_date)
ORDER BY TRUNC_HALFDAY(user.created_date)
Even though the function appears three times in your query, because it's declared DETERMINISTIC it only gets called once per row.
More complete writeup here.

ORDER BY datetime depending on the day AND time

I have a database field of type datetime.
The name of this field is "recallDate"
I would like to order the results in the following way:
The results must be chronological in the time: from newest to oldest
The results must be grouped by date: in other words, result having the same date are together, grouped
For every day, the results must be chronological according to the hour: earliest to latest
The results having no hour ( 00:00:00 ) have to be at the end of the results of the day
This is my actual query :
SELECT a.recallDate, a.id, a.id_company, com.name, a.recallType
FROM PDT_CRM.actions a
INNER JOIN PDT_CRM.traders as trad on trad.id=a.id_traders
WHERE DATE(a.recallDate) > DATE(NOW() + INTERVAL 30 DAY)
ORDER BY TIME(a.recallDate) , a.recallType
It is very likely that I have to use CASE but I don't understand how to use it.
You can use the following code to create a specific order that will put times '00:00:00' at the very end of the day:
...
ORDER BY date(a.rappelDate),
case when time(a.rappelDate) = 0 then 1 else 0 end,
time(a.rappelDate)

using mysql datediff with an elseif or case statement

I have the following line of code that can either return one of 2 conditions ('Expired','Active'). I needed to use DATEDIFF to figure out the dates I needed.
However, now I need to alter this code so that I can add a sort of else if condition if neither of the 2 conditions are met and result to 'Unknown'.
I have this so far:
SELECT
IF(DATEDIFF(#endDate:=ADDDATE(h.StartDate,Interval h.NumMonth Month),NOW())<0,'Expired',
IF(DATEDIFF(#endDate,NOW())<120,'Expires in 120 days or less','Active')) AS bActive
FROM ...
So, for now, I have Expired, Active but I also want to include else 'Unknown' to be included as option. How would I alter this logic? Do I need to use ELSEIF or CASE? What should I use?
Use case instead of if. First, case is ANSI standard, so it works across databases. Second, it handles multiple conditions better. I think your logic is:
SELECT (CASE WHEN DATEDIFF(ADDDATE(h.StartDate, Interval h.NumMonth Month), NOW()) < 0
THEN 'Expired'
WHEN DATEDIFF(ADDDATE(h.StartDate, Interval h.NumMonth Month), NOW()) < 120
THEN 'Expires in 120 days or less'
ELSE 'Active'
END) AS bActive

How to select based on different column data

I want to perform a different SELECT based on the column data. For example I have a table http://sqlfiddle.com/#!2/093a2 where I want compare start_date and end_date only if use_schedule = 1. Otherwise select all data. (A different select) Basically I only want to compare the start and end date if only use_schedule is 1 and if use_schedule is 0 then select rest of the data.
An example may be something like
select id, name from table
where use_schedule = 0
else
select id, name, start_date from table
where use_schedule = 0 and current_date >= start_date.
Basically I have the data where schedule is enabled only then look into start and end date. Because if schedule is not enabled there is no point of looking into the dates. Just select the data. With schedule enabled, I want to be more selective in selecting the scheduled data.
I am trying to figure out if MySQL CASE or IF statements would work but not able to do so. How can I run this select?
Thanks.
You can use UNION to mix and match the results of 2 different SQL queries into one result set:
select id, name, null from table
where use_schedule = 0
union
select id, name, start_date from table
where use_schedule = 1 and current_date >= start_date
Note that both queries have to have compatible output fields (same number and type for this to work). The use of UNION automatically merges only distinct records - if you want to keep double results use UNION ALL instead.
In this specific case a more extensive WHERE-clause would also work obviously:
where use_schedule = 0 or (use_schedule = 1 and current_date >= start_date)
But given the question I'm assuming your real case is a bit more complex.
Documentation over at MySQL site.
Use CASE, in this case..:
SELECT id, name,
(CASE
WHEN start_date >= DATE(NOW()) AND use_schedule = 1
THEN start_date
ELSE NULL
END) AS cols FROM campaigns
This way it selects only the schedule 0 OR the 1 with a date bigger or equals to now;
I used DATE(NOW()) so that it removes the time which you are not interested in.

Execute a subquery in MySQL that returns multiple rows?

I am executing a query that obviously contains a subquery in MySQL.
Let me just jump into the code:
SELECT DATEDIFF(CURDATE(),
(SELECT due FROM checkOut JOIN People ON checkOut.p_id = People.p_id
WHERE CASE WHEN DATE_SUB(date_add(CURDATE(),INTERVAL 4 MONTH), INTERVAL 3 MONTH)
>= checkOut.checkTime THEN 1 ELSE 0 END ORDER BY checkOut.due)
);
The main query is the SELECT DATEDIFF(). Within that is my subquery which essentially searches through the table to look for items that are overdue based on an interval. I know that there will be multiple rows returned from the query and that it will not work with how I currently have it set up.
What I want are multiple values to be returned from my SELECT DATEDIFF(), so that I can loop through it with php later. To elaborate, I want each of the rows returned in the subquery to have an associated value from DATEDIFF(). How can I modify this query to do what I want? Or if anyone has a better method, please let me know.
Any help is appreciated.
In case you are wondering the why there is a DATE_ADD() within the DATE_SUB(), it is to simply make the query work for today.
get rid of the subquery, you can calculate the difference directly.
SELECT DATEDIFF(CURDATE(), due), due
FROM checkOut JOIN People
ON checkOut.p_id = People.p_id
WHERE CASE
WHEN DATE_SUB(date_add(CURDATE(),INTERVAL 4 MONTH), INTERVAL 3 MONTH)
>= checkOut.checkTime
THEN 1
ELSE 0
END
ORDER BY checkOut.due
Use the subquery as table. e.g. below:
SELECT DATEDIFF(CURDATE(), d.due)
FROM
(SELECT due FROM checkOut JOIN People ON checkOut.p_id = People.p_id
WHERE CASE WHEN DATE_SUB(date_add(CURDATE(),INTERVAL 4 MONTH), INTERVAL 3 MONTH)
>= checkOut.checkTime THEN 1 ELSE 0 END ORDER BY checkOut.due)
) AS d;