MySQL - How to find records for yesterday when timestamp is part of date - mysql

My MySQL table stores records with a date/time stamp. I am wanting to find records from the table that were created yesterday (as in have a creation date of yesterday - regardless of what the timestamp portion is)
Below is what a db record looks like:
I have tried the following select (and a few other variations, but am not getting the rows with yesterday's date.
SELECT m.meeting_id, m.member_id, m.org_id, m.title
FROM meeting m
WHERE m.create_dtm = DATE_SUB(CURDATE(), INTERVAL 1 DAY)
Not exactly sure how I need to structure the where clause to get meeting ids that occurred yesterday. Any help would be greatly appreciated.

A naive approach would truncate the creation timestamp to date, then compare:
where date(m.create_dtm) = current_date - interval 1 day
But it is far more efficient to use half-open interval directly against the timestamp:
where m.create_dtm >= current_date - interval 1 day and m.create_dtm < current_date

You can try next queries:
SELECT
m.meeting_id, m.member_id, m.org_id, m.title, m.create_dtm
FROM meeting m
-- here we convert datetime to date for each row
-- it can be expensive for big table
WHERE date(create_dtm) = DATE_SUB(CURDATE(), INTERVAL 1 DAY);
SELECT
m.meeting_id, m.member_id, m.org_id, m.title, m.create_dtm
FROM meeting m
-- here we calculate border values once and use them
WHERE create_dtm BETWEEN DATE_SUB(CURDATE(), INTERVAL 1 DAY) AND DATE_SUB(CURDATE(), INTERVAL 1 SECOND);
Here live fiddle: SQLize.online

Related

mysql optimize query where date hour

Hi all, I have pretty awfull query, that needs optimizing.
I need to select all records where date of created matches NOW - 35days, but the minutes and seconds can be any.
So I have this query here, its ugly, but working:
Any optimisation tips are welcome!
SELECT * FROM outbound_email
oe
INNER JOIN (SELECT `issue_id` FROM `issues` WHERE 1 ORDER BY year DESC, NUM DESC LIMIT 0,5) as issues
ON oe.issue_id = issues.issue_id
WHERE
year(created) = year( DATE_SUB(NOW(), INTERVAL 35 DAY) ) AND
month(created) = month( DATE_SUB(NOW(), INTERVAL 35 DAY) ) AND
day(created) = day( DATE_SUB(NOW(), INTERVAL 35 DAY) ) AND
hour(created) = hour( DATE_SUB(NOW(), INTERVAL 35 DAY) )
AND campaign_id IN (SELECT id FROM campaigns WHERE initial = 1)
I assume the field "created" is a datetime field and is from the issues table? Since you don't need anything else on the issues and campaign table, then you can do the following:
SELECT e.* FROM outbound_email e
JOIN issues i ON e.issue_id = i.issue_id
JOIN campaigns c ON c.id = i.campaign_id
WHERE i.created < DATE_SUB(NOW(), INTERVAL 35 DAY)
AND c.initial = 1
There's no need to separate the datetime field into years, months...etc.
You seem to be saying you want to select all rows from a table where the time they were created was the same hour as it is currently, 35 days ago
SELECT * FROM table WHERE created BETWEEN
DATE_ADD(CURDATE(), INTERVAL (HOUR(now()) - 840) HOUR) AND
DATE_ADD(CURDATE(), INTERVAL (HOUR(now()) - 839) HOUR)
Why does it work? Curdate gives us today at midnight. We add to this the current hour of the time (e.g. Suppose it's now 5pm we'd add `HOUR(NOW()) which would give us 17, for a time now of 5pm) but we also subtract 840 because that's 35 days * 24 hours a day = 840 hours. Date add will hence add -823 hours to the current date, i.e. 5pm 35 days ago
We make the search a range to get all the records from the hour, the simplest way to specify an hour later is to subtract 839 hours instead of 840
Technically this query will also return records that are bang on 6pm (but not a second later) 35 days ago too because between is inclusive (between 1 and 10 will return 10 also
If this is a problem, change the BETWEEN for created >= blah AND created < blahblah
I haven't put the rest of your query in for reasons of clarity
As a side note, the way you did it wasn't bad- you could have simplified things by not having the year/month/day parts, just dropping the time part of the date with date(created) = date_sub(curdate(), interval 35 day) which is the year month and day combined as a date, no time element.. BUT it is generally always best to leave table data alone rather than format or convert it just to match a query. If you convert table data then indexes can no longer be used. If you go the extra mile to get your query parameters into the format of the column, and don't convert the table data then indexes on the column can be used

mysql arithmetik operation (subtraction) last - first of the day(week, month)

i got a MySQL tbl, with some colums, where every 5 min. a new row is inserted with 3 values
1. Auto inc. curent Date Unix timestamp --> date
2. power consumption absolut --> wert01
3. Power Generation absolut --> wert02
To Show this Information in a Graph, for Exampl for weekly power consumption, i need to select the First and the last, which allready Works, but then have to Substract the last from the First and Show only tue result & the day of the werk.
SELECT
(SELECT wert01
FROM sml_splitt
WHERE date >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY
AND date < curdate() - INTERVAL DAYOFWEEK(curdate()) DAY
ORDER BY date DESC LIMIT 1) AS 'last',
(SELECT wert01
FROM sml_splitt
WHERE date >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY
AND date < curdate() - INTERVAL DAYOFWEEK(curdate()) DAY
ORDER BY date LIMIT 1) AS 'lirst
I am searching for some days to find a solution, but with no success.
Hopfuly, you could help me.
If you're happy with your query, then you can do the math by nesting it one more time like this: http://sqlfiddle.com/#!9/515ef/1
select t1.last, t1.first, t1.last - t1.first as result
from (
select (
select wert01
from sml_splitt
where dt >= curdate() - interval dayofweek(curdate()) + 6 day
and dt < curdate() - interval dayofweek(curdate()) day
order by dt desc limit 1
) as 'last',
(
select wert01
from sml_splitt
where dt >= curdate() - interval dayofweek(curdate()) + 6 day
and dt < curdate() - interval dayofweek(curdate()) day
order by dt limit 1
) as 'first'
) t1
;
If you really want to work with this data by week for reporting purposes, let me suggest a couple of views. The first will give you all of your distinct beginning of week dates:
create view v1 as
select date(dt) as week_begins
from sml_splitt
where dayofweek(dt) = 1
group by week_begins
The second view joins the first view with itself to give you a week beginning and week ending range:
create view v2 as
select t1.week_begins, coalesce(t2.week_begins,now()) as week_ends
from v1 t1
left join v1 t2
on t2.week_begins = t1.week_begins + interval 7 day
You can see the results here: http://sqlfiddle.com/#!9/a4d1b3/2. Notice that I'm using now() to get the current date and time if the week hasn't ended yet.
From there you can join your view with your original table and use min() and max() function with grouping to get the starting and ending 'wert' values and do any calculations on them that you like.
Here's an example: http://sqlfiddle.com/#!9/a4d1b3/6
select week_begins, week_ends,
min(wert01) as start_wert01,
max(wert01) as end_wert01,
max(wert01) - min(wert01) as power_consumed,
min(wert02) as start_wert02,
max(wert02) as end_wert02,
max(wert02) - min(wert02) as power_generated,
(max(wert02) - min(wert02)) - (max(wert01) - min(wert01)) as net_generated
from v2
inner join sml_splitt
on sml_splitt.dt >= v2.week_begins
and sml_splitt.dt < v2.week_ends
group by week_begins
I hope that helps.

how to filter a select statement in mysql for a particular time period without using now()

I have tried to filter records but with the use of now function as given below
select * from table where date>= DATE_SUB( NOW( ) ,INTERVAL 90 DAY )
What I need is a select statement that can filter its records for a week or month from the current date but without using NOW() function
if you are using java you could make use of the following code
String timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime());
or you could use curdate() of mysql
Since I found it hard to understand the question I provide the following possibilities:
Try for all dates in a week from now:
SELECT * FROM table
WHERE date BETWEEN CURDATE() AND DATE_ADD(CURDATE() ,INTERVAL 1 WEEK)
and for all dates in a month from now:
SELECT * FROM table
WHERE date BETWEEN CURDATE() AND DATE_ADD(CURDATE() ,INTERVAL 1 MONTH)
If you are looking for all dates of the current month use
SELECT * FROM table
WHERE MONTH(date)=MONTH(CURDATE()) AND YEAR(date)=YEAR(CURDATE())
or for all dates of the current week use
SELECT * FROM table
WHERE WEEK(date)=WEEK(CURDATE()) AND YEAR(date)=YEAR(CURDATE())

Return row count between 2 dates always returns 0

wonder if any aficionados can help me. I am trying to get the number of records between two dates, I made this query really simple using some posts i found on here, it always returns 0.
date_added is a timestamp
SELECT COUNT(id)
FROM item
WHERE date_added >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND date_added <= NOW()
I also tried this:
SELECT COUNT(id)
FROM item
WHERE date_added BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND NOW()
What am I doing wrong?
Use DATE(NOW()) and DATE(date_added) for comparison of dates in mysql. It will give you date part of the timestamp.
For Example
CURDATE() is 2008-11-11 and
NOW() is 2008-11-11 12:45:34
One is date, other is timestamp. You should take either both dates or both timestamp. One solution I've told above.
I re ran this query this morning and it worked just fine, so I'm not sure what went wrong last night other than the hour. Thanks to everyone's input.
SELECT COUNT(id)
FROM item
WHERE date_added BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE()
worked fine as did
SELECT COUNT(id)
FROM item
WHERE DATE(date_added) BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE()
Hope that may be of use to someone.

How to do : "Between TODAY AND TODAY-7"?

I need to find the account created for the current day, et for the last 7 days.
To find my results for today, it works, and I do this :
SELECT * FROM `account` where DATE(created_at) = DATE(NOW())
But I don't know how to do to get the last 7days account.
I tried something like this, but without success :
SELECT * FROM `account` where DATE(created_at) BETWEEN DATE(NOW()) AND DATE(NOW()-7)
Have you an idea ?
in mysql:
SELECT * FROM `account`
WHERE DATE(created_at) > (NOW() - INTERVAL 7 DAY)
Try:
BETWEEN (NOW() - INTERVAL 7 DAY) AND NOW()
If created_at has an index and you wouldn't like to prevent the optimiser from using it, I would recommend the following pattern (assuming created_at contains both date and time):
WHERE created_at >= CURRENT_DATE - INTERVAL 7 DAY
AND created_at < CURRENT_DATE + INTERVAL 1 DAY
This spans the range from the day exactly one week ago till today (inclusive), so 8 days in total.
also have a look at MySQL functions ADDDATE(), DATE_ADD(), DATE_SUB()
e.g.
ADDDATE(DATE(NOW()), -7)