MySQL Select last 7 days - mysql

I read some posts here and seems like nothing special but I can not still select the entries of the last days.
SELECT
p1.kArtikel,
p1.cName,
p1.cKurzBeschreibung,
p1.dLetzteAktualisierung,
p1.dErstellt,
p1.cSeo,
p2.kartikelpict,
p2.nNr,
p2.cPfad
FROM
tartikel AS p1 WHERE DATE(dErstellt) > (NOW() - INTERVAL 7 DAY)
INNER JOIN
tartikelpict AS p2
ON (p1.kArtikel = p2.kArtikel) WHERE (p2.nNr = 1)
ORDER BY
p1.kArtikel DESC
LIMIT
100;', $connection);
If I add the between today and last 7 days my Code will not output anything.

The WHERE clause is misplaced, it has to follow the table references and JOIN operations.
Something like this:
FROM tartikel p1
JOIN tartikelpict p2
ON p1.kArtikel = p2.kArtikel
AND p2.nNr = 1
WHERE p1.dErstellt >= DATE(NOW() - INTERVAL 7 DAY)
ORDER BY p1.kArtikel DESC
EDIT (three plus years later)   
The above essentially answers the question "I tried to add a WHERE clause to my query and now the query is returning an error, how do I fix it?"
As to a question about writing a condition that checks a date range of "last 7 days"...
That really depends on interpreting the specification, what the datatype of the column in the table is (DATE or DATETIME) and what data is available... what should be returned.
To summarize: the general approach is to identify a "start" for the date/datetime range, and "end" of that range, and reference those in a query. Let's consider something easier... all rows for "yesterday".
If our column is DATE type. Before we incorporate an expression into a query, we can test it in a simple SELECT
SELECT DATE(NOW()) + INTERVAL -1 DAY
and verify the result returned is what we expect. Then we can use that same expression in a WHERE clause, comparing it to a DATE column like this:
WHERE datecol = DATE(NOW()) + INTERVAL -1 DAY
For a DATETIME or TIMESTAMP column, we can use >= and < inequality comparisons to specify a range
WHERE datetimecol >= DATE(NOW()) + INTERVAL -1 DAY
AND datetimecol < DATE(NOW()) + INTERVAL 0 DAY
For "last 7 days" we need to know if that mean from this point right now, back 7 days ... e.g. the last 7*24 hours , including the time component in the comparison, ...
WHERE datetimecol >= NOW() + INTERVAL -7 DAY
AND datetimecol < NOW() + INTERVAL 0 DAY
the last seven complete days, not including today
WHERE datetimecol >= DATE(NOW()) + INTERVAL -7 DAY
AND datetimecol < DATE(NOW()) + INTERVAL 0 DAY
or past six complete days plus so far today ...
WHERE datetimecol >= DATE(NOW()) + INTERVAL -6 DAY
AND datetimecol < NOW() + INTERVAL 0 DAY
I recommend testing the expressions on the right side in a SELECT statement, we can use a user-defined variable in place of NOW() for testing, not being tied to what NOW() returns so we can test borders, across week/month/year boundaries, and so on.
SET #clock = '2017-11-17 11:47:47' ;
SELECT DATE(#clock)
, DATE(#clock) + INTERVAL -7 DAY
, #clock + INTERVAL -6 DAY
Once we have expressions that return values that work for "start" and "end" for our particular use case, what we mean by "last 7 days", we can use those expressions in range comparisons in the WHERE clause.
(Some developers prefer to use the DATE_ADD and DATE_SUB functions in place of the + INTERVAL val DAY/HOUR/MINUTE/MONTH/YEAR syntax.
And MySQL provides some convenient functions for working with DATE, DATETIME and TIMESTAMP datatypes... DATE, LAST_DAY,
Some developers prefer to calculate the start and end in other code, and supply string literals in the SQL query, such that the query submitted to the database is
WHERE datetimecol >= '2017-11-10 00:00'
AND datetimecol < '2017-11-17 00:00'
And that approach works too. (My preference would be to explicitly cast those string literals into DATETIME, either with CAST, CONVERT or just the + INTERVAL trick...
WHERE datetimecol >= '2017-11-10 00:00' + INTERVAL 0 SECOND
AND datetimecol < '2017-11-17 00:00' + INTERVAL 0 SECOND
The above all assumes we are storing "dates" in appropriate DATE, DATETIME and/or TIMESTAMP datatypes, and not storing them as strings in variety of formats e.g. 'dd/mm/yyyy', m/d/yyyy, julian dates, or in sporadically non-canonical formats, or as a number of seconds since the beginning of the epoch, this answer would need to be much longer.

Since you are using an INNER JOIN you can just put the conditions in the WHERE clause, like this:
SELECT
p1.kArtikel,
p1.cName,
p1.cKurzBeschreibung,
p1.dLetzteAktualisierung,
p1.dErstellt,
p1.cSeo,
p2.kartikelpict,
p2.nNr,
p2.cPfad
FROM
tartikel AS p1 INNER JOIN tartikelpict AS p2
ON p1.kArtikel = p2.kArtikel
WHERE
DATE(dErstellt) > (NOW() - INTERVAL 7 DAY)
AND p2.nNr = 1
ORDER BY
p1.kArtikel DESC
LIMIT
100;

Related

select data on specific date

I want to retrieve records from db according to date format YYYY,MM,dd given by me but the column type is YYYY,MM,dd hh:mm:ss.
tried to use Date format function
SELECT *
FROM tabl.error_logs
where created_at = DATE_FORMAT(NOW(),'%Y-%m-%d'- INTERVAL 3 DAY);
I expect the created date will be 2019-06-08, but the result is empty
What is the actual datatype of created_at column?
This answer is going to ignore that funkiness with the format with commas, and assume that it's not character type data, and that it's DATETIME or TIMESTAMP.
Normative pattern for predicates on DATETIME and TIMESTAMP columns is a range comparison.
For example, to get all datetimecol values on June 10th, then something like this:
WHERE t.datetimecol >= '2019-06-10 00:00:00'
AND t.datetimecol < '2019-06-11 00:00:00'
Typically, I would just pass that one date value, and let MySQL figure out the next day. If we omit the time portion, MySQL will assume 00:00:00
WHERE t.datetimecol >= '2019-06-10' + INTERVAL 0 DAY
AND t.datetimecol < '2019-06-10' + INTERVAL 1 DAY
For performance, to allow MySQL to make effective use of a range scan operation on a suitable index, we want to avoid wrapping the column reference in a function. That is, specifying DATE(t.datetimecol) in a condition in the WHERE clause is going to force MySQL to evaluate the DATE() function on every row in the table.
With references to the bare column, that allows MySQL to make use of an index, if a suitable index is available.
e.g.
SELECT e.*
FROM tabl.error_logs e
WHERE e.created_at >= DATE(NOW()) + INTERVAL -3 DAY
AND e.created_at < DATE(NOW()) + INTERVAL -2 DAY
note that we can easily test those expressions in the WHERE clause, to verify they are returning what we want, and tweak as necessary:
SELECT DATE(NOW()) + INTERVAL -3 DAY
, DATE(NOW()) + INTERVAL -2 DAY
To make your query sargable, you need ...
SELECT *
FROM tabl.error_logs
WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 3 DAY)
AND created_at < DATE_SUB(CURDATE(), INTERVAL 2 DAY)
This selects all values of created_at on or after midnight three days ago, up to but not including < midnight two days ago. It uses a range scan on an index on created_at if one is available.
You coudl use date_sub()
SELECT *
FROM tabl.error_logs
where date(created_at) = DATE_SUB(date(now()), INTERVAL 3 DAY);
if the column created_at is a date then you could avoid the date() function and let the index (if present) work for this column
SELECT *
FROM tabl.error_logs
where created_at = DATE_SUB(date(now()), INTERVAL 3 DAY);

MSQL, Query rows passed a certain date of an initial date?

How do i extract all rows greater then 7 days of a start date?, I'm trying to use this query in MySQL. Below is my statement.
SELECT * from v_polygons a
INNER JOIN tblProjectData z
on z.Project_ID = a.Project_ID
WHERE DATE_ADD(z.FlyDate, INTERVAL 7 DAY) > NOW() + INTERVAL rge DAY
I have a start date z.FlyDate, So i give it +7 days, then i check to see if that date is greater then NOW()
is this correct or have i messed it up?
You can just do:
WHERE DATE_ADD(DATE(z.FlyDate), INTERVAL 7 DAY) < DATE(NOW());
This will ignore the time part. You can remove DATE function call if you want to consider the time as well.

Select all MySQL records in the last day that are between a time range of 7am and midnight

I have this query
SELECT * FROM `timeclock_timecard`
WHERE `clock_in_datetime` > DATE_SUB(CURDATE(), INTERVAL 1 DAY)
which can get record in the last day but I need to limit to records created after 7AM
Any help please?
SELECT * FROM `timeclock_timecard`
WHERE `clock_in_datetime` > DATE_SUB(CURDATE(), INTERVAL 1 DAY)
and hour(`clock_in_datetime`) > 7;
Added one more filter condition to check for the hour.
Your query was almost correct, because CURDATE() only gives the date you can just subtract 17 hours to get the correct result. fiddle.
SELECT * FROM `timeclock_timecard`
WHERE `clock_in_datetime` >= DATE_SUB(CURDATE(), INTERVAL 17 HOUR)
To get the entries of the current day, we can add 7 hours (CURDATE() has time 0:00).
SELECT * FROM `timeclock_timecard`
WHERE `clock_in_datetime` >= DATE_ADD(CURDATE(), INTERVAL 7 HOUR)
To get only rows from yesterday, with a time value of 7AM or later, we can add 7 hours to the expression.
If we only up until midnight of today (just rows from yesterday), we can add another condition, the datetime is less than midnight today.
For example:
SELECT t.*
FROM `timeclock_timecard` t
WHERE t.`clock_in_datetime` >= DATE(NOW()) + INTERVAL -1 DAY + INTERVAL 7 HOUR
AND t.`clock_in_datetime` < DATE(NOW())
If you want to exclude the exact 7:00:00 AM value, change the >= to just >.
FOLLOWUP
Q: What I actually want is between about 5-6am TODAY and mindnight TODAY so anytime during today that I run the report for today I will get only timeclock data from users who clocked in/out today only and not include yesterdays data.
A: The predicates are going to be of the form
WHERE t.`clock_in_datetime` >= expr1
AND t.`clock_in_datetime` < expr2
You just need to find the expressions expr1 and expr2 that return the appropriate datetime values.
Just use a simple SELECT statement to test:
SELECT DATE(NOW()) + INTERVAL 5 HOUR AS `start`
, DATE(NOW()) + INTERVAL 1 DAY AS `end`
Q: I also modified my select to take in account my datetime is in UTC and my result needs to get todays records using local timezone.
SELECT * , CONVERT_TZ( clock_in_datetime , '+00:00', '-4:00' ) FROM `timeclock_timecard`
A: Personally, I would do the timezone conversion on the exprN values, not the column values. Having predicates on bare columns allows MySQL to make effective use of an index; wrapping the columns in expressions prevents MySQL from using an index.
If the MySQL system clock is UTC, and your datetime values stored in the table are in a different timezone, yes, use the MySQL CONVERT_TZ function.
Again, using a simple SELECT statement to develop and test the expressions:
SELECT CONVERT_TZ( DATE(NOW()) + INTERVAL 5 HOUR, '+0:00', to_tz) AS `start`
, CONVERT_TZ( DATE(NOW()) + INTERVAL 1 DAY , '+0:00', to_tz) AS `end`
Where to_tz is the timezone of the values in the table.
Once you get expressions start and end returning the values you need, then use those expressions in the predicates of the query of the timecard table.

Trouble with date ranges

I need to check for entries made in the last "x" days (example 30 days) and cannot get the query to work. This is what I am using:
SELECT CAL_OWNER,
CAL_TITLE,
FROM_UNIXTIME (CAL_CREATED, "%m-%d-%y") AS CREATED,
FROM_UNIXTIME (RANGE_START, "%Y-%m-%d") AS DATE2BESEEN,
CASE CAL_REFERRAL_TYPE
WHEN 1 THEN 'NoReferral'
WHEN 2 THEN 'CareyGuide'
WHEN 3 THEN 'Education'
WHEN 4 THEN 'Employment'
WHEN 5 THEN 'Housing'
WHEN 6 THEN 'Medical'
ELSE 'NA'
END
AS REFERRALS
FROM EGW_CAL
WHERE CAL_CREATED BETWEEN (NOW () - '30 day') AND NOW ()
ORDER BY REFERRALS ASC;
If I comment out the "WHERE range_start ... line the query runs fine, but pulls all data
However, if I run the complete query, it does not error, but there are no results (I have 4 entries in column cal_created in the last 3 weeks).
If some one can help I'd really appreciate it
Try using INTERVAL and either NOW() or CURDATE()..
WHERE FROM_UNIXTIME (CAL_CREATED,'%Y-%m-%d') BETWEEN CURDATE() - INTERVAL 30 DAY AND CURDATE()
curdate is just the date portion of the day
if you want to include the time use NOW()
WHERE FROM_UNIXTIME (CAL_CREATED,'%Y-%m-%d') BETWEEN NOW() - INTERVAL 30 DAY AND NOW()
you could also make a new date to use the between with
WHERE FROM_UNIXTIME (CAL_CREATED,'%Y-%m-%d') BETWEEN DATE_SUB(NOW(), INTERVAL 30 DAY) AND NOW()
SOURCE: http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
NOTE: the dates need to be formatted correctly in order for it to work
FULL QUERY:
SELECT
CAL_OWNER,
CAL_TITLE,
FROM_UNIXTIME (CAL_CREATED, '%m-%d-%y') AS CREATED_AT,
FROM_UNIXTIME (RANGE_START, '%Y-%m-%d') AS DATE2BESEEN,
CASE CAL_REFERRAL_TYPE
WHEN 1 THEN 'NoReferral'
WHEN 2 THEN 'CareyGuide'
WHEN 3 THEN 'Education'
WHEN 4 THEN 'Employment'
WHEN 5 THEN 'Housing'
WHEN 6 THEN 'Medical'
ELSE 'NA'
END AS REFERRALS
FROM EGW_CAL
WHERE FROM_UNIXTIME(CAL_CREATED,'%Y-%m-%d') BETWEEN (NOW() - INTERVAL 30 DAY) AND NOW()
ORDER BY REFERRALS ASC;
CAL_CREATED is a UNIX timestamp,
NOW() will return a MySQL timestamp.
They don't mix automatically. So use
WHERE CAL_CREATED
BETWEEN UNIX_TIMESTAMP(NOW() - INTERVAL 30 DAY) AND UNIX_TIMESTAMP(NOW());
Note:
I wouldn't recommend to go the other way
WHERE FROM_UNIXTIME(CAL_CREATED) BETWEEN ...
because MySQL can't use an index in this case.
The correct where clause uses internval:
WHERE CAL_CREATED BETWEEN NOW() - interval 30 day AND NOW()
The use of single quotes is reminiscent of Postgres. In MySQL, it ends up treating the value of now() as an integer. And it subtracts the string value "30 days" from it.
When now() is treated as an integer, it also has hours, minutes, and seconds. So you are really subtracting something like 30 seconds. Here is the documentation on now().

Mysql Datediff query

I need to get the result from the table, which the date should be difference of 5 from the current date.
ie., specific_date column is present in my table. The format of the date is YYYY-MM-DD.
I need the query something like,
SELECT * FROM `table_name` WHERE DATEDIFF(NOW(), specific_date) < 5
It looks like you are trying to do this:
WHERE specific_date < (NOW() + 5 days)
First of all, think carefully about the boundary cases. These boundary cases can bite your ankles in SQL. Do you actually want
WHERE specific_date <= (NOW() + 5 days)
Do your specific_date columns timestamps contain only days (that is dates with times equal to midnight) or do they contain dates and times? If you're going to get the results you want, you need to be careful about those details.
At any rate, try this:
WHERE specific_date <= DATE_ADD(NOW(), INTERVAL 5 DAY)
This is a good way to do such a lookup. The column value stands alone on one side of the inequality predicate (the <=) so mySQL can do an index range scan if you have an index on the column.
Date arithmetic in MySQL is quite flexible. You can do
NOW() + INTERVAL 10 SECOND
NOW() - INTERVAL 2 MINUTE
NOW() + INTERVAL 4 HOUR
CURDATE() - INTERVAL 1 WEEK /* midnight one week ago */
LAST_DAY(NOW()) + INTERVAL 1 DAY - INTERVAL 1 MONTH /*first day of present month*/
NOW() - INTERVAL 1 QUARTER
CURDATE() - INTERVAL 5 YEAR
and so forth.
Have a look at the BETWEEN operator.
expr BETWEEN min AND max
Another way is to use the DATE_SUB operator
WHERE date_column > DATE_SUB(NOW(), INTERVAL 5 DAY)