What is REALLY inside that field? - mysql

In MYSQL I have a '0' inserted into a DATETIME field called DT.
making it a "0000-00-00 00:00:00".
I need to compare DT to NOW() and tell if the result is in the past or not.
Some dates have real values, and some dates have a '0' (as said get the "0000-00-00 00:00:00").
How can I check that column DT + INTERVAL 3 MONTH < NOW() ?
Thanks!

It seems like you just want to ignore the 0 dates, so you can simply filter out the 0 dates in your WHERE clause like this:
SELECT * FROM mytable
WHERE DT != '0000-00-00 00:00:00'
AND DATE_ADD(DT, INTERVAL 3 MONTH) < NOW()
Here's the optimized version of that query. You should try to put your functions on the right side of the criteria so that MySQL can utilize indexes:
SELECT * FROM mytable
WHERE DT != '0000-00-00 00:00:00'
AND DT < DATE_ADD(NOW(), INTERVAL -3 MONTH)

You can use the DATE_ADD() function to get what you are looking for:
SELECT * FROM mytable WHERE DATE_ADD(`DT`, INTERVAL 3 MONTH) < NOW();
This will return all columns where (DT + INTERVAL 3 MONTH) < NOW()

Related

mysql select between two dates has odd behavior

I am selecting all records between NOW() and specific X day interval and came across this odd behavior that I don't understand.
I am checking 24 hours into the future and 24 hours into the past:
select * from table where date between NOW() and NOW() + 1 interval day; //works
select * from table where date between NOW() and NOW() - 1 interval day; //no records
But if I reverse the between call:
select * from table where date between NOW() + 1 interval day AND NOW(); //no records
select * from table where date between NOW() - 1 interval day AND NOW(); //works
Why does one call into the future work, but the same call into the past not work?...and if I reverse between parameters, the opposite behavior happens - does not work 24 hours into the future but does work 24 hours into the past.
======================
Adding #TimBiegeleisen explanation below here written out:
date = '2018-05-30' ;
select * from table where date between NOW() and NOW() + 1 interval day;
= date >= '2018-05-30' AND 'date <= 2018-05-31'; //true
select * from table where date between NOW() and NOW() - 1 interval day; records
= date >= '2018-05-30' AND 'date <= 2018-05-29'; //false
AND
select * from table where date between NOW() + 1 interval day AND NOW();
= date >= '2018-05-31' AND date <= '2018-05-30' //false
select * from table where date between NOW() - 1 interval day AND NOW();
= date >= '2018-05-29' and date <= '2018-05-30'; //true
The BETWEEN operator is interpreted a certain way:
WHERE date BETWEEN a AND b
means this:
WHERE date >= a AND date <= b
So the following two queries are equivalent:
select * from table where date between NOW() and NOW() - interval 1 day;
select * from table where date >= NOW() and date <= NOW() - interval 1 day;
Hopefully you can see that in your second query the WHERE condition can never be true, because a date cannot simutaneously be greater than or equal to now and less than now minus one at the same time.
simply put,
For SQL:
WHERE x between a and b
meaning
x >= a
and
x <= b
therefore, we have a <= x <= b or a <= b
PS: it's just about math :)

MySQL Rolling Value - subquery with joined value

I am trying to do a single query over a period of a month. This is a working query:
SELECT AVG(days)
FROM (SELECT datediff(IF(MIN(date_end) = '0000-00-00', DATE(NOW()), MAX(date_end)), MIN(date_start)) AS days
FROM tenancies
WHERE deleted_at IS NULL AND date_start < DATE_SUB(NOW(), INTERVAL 1 MONTH)
GROUP BY tenancies.tenant_id)
I want to replace NOW() with a date.
I have another query:
SELECT calendar_date
FROM calendar_dates
WHERE calendar_date BETWEEN NOW() - INTERVAL 1 MONTH AND NOW()
This gets me all the dates I want. If I try to do a double-subquery it doesn't recognize the calendar_date:
SELECT calendar_date, (SELECT AVG(days)
FROM (SELECT datediff(IF(MIN(date_end) = '0000-00-00', DATE(calendar_date), MAX(date_end)), MIN(date_start)) AS days
FROM tenancies
WHERE deleted_at IS NULL AND date_start < DATE_SUB(calendar_date, INTERVAL 1 MONTH)
GROUP BY tenancies.tenant_id) d) AS days
FROM calendar_dates
WHERE calendar_date BETWEEN NOW() - INTERVAL 1 MONTH AND NOW()
Anyone have any suggestions?
I assume it does not recognize DATE(calendar_date) and DATE_SUB(calendar_date, INTERVAL 1 MONTH), If right, Your tenancies table should have a calendar_date field in itself, otherwise you need to join tenancies with calendar_dates table in the middle query too. Because thats a separate query.

How do I subtract two results from a SELECT statement within that statement?

This pulls back two int values of yesterday and today. I'd like to subtract the two results from within the statement in a third column called difference:
SELECT (
SELECT COUNT(*)
FROM collectors_users
WHERE DATE(dateadded) = CURDATE() - INTERVAL 1 DAY
) AS yesterday, COUNT(*) AS today
FROM collectors_users
WHERE DATE(dateadded) = CURDATE()
You need to repeat the expressions. SQL (in general) does not allow you to re-use column aliases in the same SELECT. You can simplify the logic to:
SELECT SUM(DATE(dateadded) = CURDATE() - INTERVAL 1 DAY) AS yesterday,
SUM(DATE(dateadded) = CURDATE()) as today,
(SUM(DATE(dateadded) = CURDATE()) -
SUM(DATE(dateadded) = CURDATE() - INTERVAL 1 DAY)
) as diff
FROM collectors_users
WHERE dateadded >= CURDATE() - INTERVAL 1 DAY AND
dateadded < CURDATE() + INTERVAL 1 DAY;
Note that the logic for the WHERE clause covers two days. Also, it does not use DATE(). This would allow the query to use an index, if available.

mySQL rows from today not last 24 hours

Basically, I've got a query which looks like the following
SELECT
*
FROM
`transactions`
WHERE
`date` > DATE_SUB(NOW(), INTERVAL 1 DAY)
AND
`status` = '1'
How can I do it so I can get it from just today, not the past 24 rolling hours; the same for a week & month etc..?
Use DATE() to get the date of your date column and compare it to today's date using CURDATE()
WHERE
DATE(`date`) = CURDATE()
Use
SELECT *
FROM `transactions`
WHERE `date` >= curdate() AND `date` < curdate() + interval 1 day
AND `status` = '1'
which can make use of indexes to speed up the query

Case in MySql when calculated values are empty for a row

I've got a long MySql string that is intended to calculate a daily percentage of a certain value. However, if there is nothing for a specific day, it just skips that day and goes to the next one. I need it to spit out a "0" for the day that it usually skips. Thanks for your help!
SELECT day(timestamp), CASE when
round(count(w_comp_current_1+W_comp_current_2)*10/86400*100,1) as 'run_time2' iS NULL
then '0'
ELSE round(count(w_comp_current_1+W_comp_current_2)*10/86400*100,1) as 'run_time2' END
FROM location.db WHERE timestamp between subdate(curdate(), interval 1 month)
and curdate() AND (w_comp_current_1+w_comp_current_2) > 45
GROUP BY MONTH(Timestamp), DAY(Timestamp)
ORDER BY Timestamp
New query using calendar table:
Select date_format(calendar.timestamp,'%b-%e') as 'Month-Day', round(count(w_comp_current_1+W_comp_current_2)*10/86400*100,1) as 'run_time2' from calendar
Left Join courthouse on calendar.timestamp = courthouse.timestamp
WHERE calendar.timestamp between subdate(curdate(), interval 1 month) and curdate() and calendar.timestamp > '2013-10-03%' AND (w_comp_current_1+w_comp_current_2) > 45
GROUP BY MONTH(calendar.Timestamp), DAY(calendar.Timestamp) ORDER BY calendar.Timestamp
You have the alias for the case column twice and both times in the wrong place. It should only be given after the case's END statement:
SELECT day(TIMESTAMP), CASE
WHEN round(count(w_comp_current_1 + W_comp_current_2) * 10 / 86400 * 100, 1) IS NULL
THEN '0'
ELSE round(count(w_comp_current_1 + W_comp_current_2) * 10 / 86400 * 100, 1)
END AS 'run_time2'
FROM location.db
WHERE TIMESTAMP BETWEEN subdate(curdate(), interval 1 month) AND curdate()
AND (w_comp_current_1 + w_comp_current_2) > 45
GROUP BY MONTH(TIMESTAMP), DAY(TIMESTAMP)
ORDER BY TIMESTAMP