Hi there :) I am doing a query, and it will pull results where the timestamp is more than 30 days old. Here's what I've put so far:
$result = $db->query("SELECT time FROM table1 WHERE open_time < (NOW() - INTERVAL 30 DAYS)");
So as you can see, it will try to find results more than 30 days old, however when I execute the query, it doesn't select any rows, even though the column field "open_time" is more than 30 days old.
Any suggestions I do greatly appreciate :)
Have you tried to cast the date field?
$result = $db->query("SELECT time FROM table1 WHERE CAST(open_time AS DATE) < (NOW() - INTERVAL 30 DAYS)");
EDIT:
Maybe you should use this tricky query:
$result = $db->query("SELECT time FROM table1 WHERE open_time <
UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))"):
Try this Query
$result = $db->query("SELECT time FROM table1 WHERE DATE(`date`) = DATE(NOW() - INTERVAL 30
DAY")
or
try this one also for your reference
timestampadd()
SELECT * FROM table WHERE `date` > timestampadd(day, -30, now());
try this link also
Now, I've a problem with the following query:
SELECT *
FROM table
WHERE date > CURDATE()
OR date = CURDATE()
AND time > CURTIME()
It's return rows with date > of today but I need also rows with date of today but with time > of the current time.
You need to put the related clauses inside parenthesis:
SELECT *
FROM table
WHERE date > CURDATE()
OR (
date = CURDATE()
AND time > CURTIME()
)
You should use the appropriate date/time functions instead of complicating yourself with complex WHERE clauses:
SELECT * FROM TABLE
WHERE ADDTIME(date, time) > NOW()
More information on the ADDTIME function in this link.
This is my scenario: I have a table that contains events, every event has a field called 'created' with the timestamp in which that event was created. Now I need to sort the events from newest to oldest, but I do not want MySQL to return them all. I need only the latest in a given interval, for example in a range of 24 hours (EDIT: I'd like to have a flexible solution, not only for a 24 hours range, but maybe every few hours). And I only need for the last 10 days. I have achieved that but i'm sure in the most inefficient ways possible, that is, something like that:
$timestamp = time();
for($i = 0; $i < 10; $i++) {
$query = "SELECT * FROM `eventos` WHERE ... AND `created` < '{$timestamp}' ORDER BY `created` DESC LIMIT 1";
$return = $database->query( $query );
if($database->num( $return ) > 0) {
$event = $database->fetch( $return );
$events[] = $event;
$timestamp = $timestamp - 86400;
}
}
I hope I was clear enough. Thanks,
Jesús.
If you have an index with created as the leading column, MySQL may be able to do a reverse scan. If you have a 24 hour period that doesn't have any events, you could be returning a row that is NOT from that period. To make sure you're getting a row in that period, you would really need to include a lower bound on the created column as well, something like this:
SELECT * FROM `eventos`
WHERE ...
AND `created` < FROM_UNIXTIME( {$timestamp} )
AND `created` >= DATE_ADD(FROM_UNIXTIME( {$timestamp} ),INTERVAL -24 HOUR)
ORDER BY `created` DESC
LIMIT 1
I think the big key to performance here is an index with created as the leading column, along with all (or most) of the other columns referenced in the WHERE clause, and making sure that index is used by your query.
If you need a different time interval, down to the second, this approach could be easily generalized.
SELECT * FROM `eventos`
WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL 0*{$nsecs} SECOND)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*{$nsecs} SECOND)
ORDER BY `created` DESC
LIMIT 1
From your code, it looks like the 24-hour periods are bounded at an arbitrary time... if the time function returns e.g. 1341580800 ('2012-07-06 13:20'), then your ten periods would all be from 13:20 on a given day to 13:20 the following day.
(NOTE: be sure that if your parameter is a unix timestamp integer, that this is being interpreted correctly by the database.)
It might be more efficient to pull the ten rows in a single query. If there is a guarantee that 'timestamp' is unique, then it's possible to craft such a query, but the query text will be considerably more complex than what you have now. We could mess with getting MAX(timestamp_) within each period, and then joining that back to get the row... but that's going to be really messy.
If I were going to try to pull all ten rows I would probably try going with a UNION ALL approach, not very pretty, but it least it could be tuned.
SELECT p0.*
FROM ( SELECT * FROM `eventos` WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL 0*24 HOUR)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*24 HOUR)
ORDER BY `created` DESC LIMIT 1
) p0
UNION ALL
SELECT p1.*
FROM ( SELECT * FROM `eventos` WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*24 HOUR)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -2*24 HOUR)
ORDER BY `created` DESC LIMIT 1
) p1
UNION ALL
SELECT p2.*
FROM ( SELECT * FROM `eventos` WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -2*24 HOUR)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -3*24 HOUR)
ORDER BY `created` DESC LIMIT 1
) p2
UNION ALL
SELECT p3.*
FROM ...
Again, this could be generalized, to pass in a number of seconds as an argument. Replace HOUR with SECOND, and replace the '24' with a bind parameter that has a number of seconds.
It's rather long winded, but it should run okay.
Another really messy and complicated way to get this back in a single result set would be to use an inline view to get the end timestamp for the ten periods, something like this:
SELECT p.period_end
FROM (SELECT DATE_ADD(t.t_,INTERVAL -1 * i.i_* {$nsecs} SECOND) AS period_end
FROM (SELECT FROM_UNIXTIME( {$timestamp} ) AS t_) t
JOIN (SELECT 0 AS i_
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
) i
) p
And then join that to your table ...
ON `created` < p.period_end
AND `created` >= DATE_ADD(p.period_end,INTERVAL -1 * {$nsecs} SECOND)
And pull back MAX(created) for each period GROUP BY p.period_end, wrap that in an inline view.
And then join that back to your table to get each row.
But that is really, really messy, hard to understand, and not likely to be any faster (or more efficient) than what you are already doing. The most improvement you could make is the time it takes to run 9 of your queries.
Assuming you want the latest (having the greatest created date) event per day for the last 10 days.
so let's get the latest timestamp per day
$today = date('Y-m-d');
$tenDaysAgo = date('Y-m-d', strtotime('-10 day'));
$innerSql = "SELECT date_format(created, '%Y-%m-%d') day, MAX(created) max_created FROM eventos WHERE date_format(created, '%Y-%m-%d') BETWEEN '$today' and '$tenDaysAgo' GROUP BY date_format(created, '%Y-%m-%d')";
Then we can select all the events that match those created dates
$outerSql = "SELECT * FROM eventos INNER JOIN ($innerSql) as A WHERE eventos.created = A.max_created";
I haven't had a chance to test this, but the principles should be sound enough.
If you want to group by some other arbitrary number of hours you would change innerSql:
$fromDate = '2012-07-06' // or if you want a specific time '2012-07-06 12:00:00'
$intervalInHours = 5;
$numberOfIntervals = 10;
$innerSql = "SELECT FLOOR(TIMESTAMPDIFF(HOUR, created, '$fromDate') / $intervalInHours) as grouping, MAX(created) as max_created FROM eventos WHERE created BETWEEN DATE_SUB('$fromDate', INTERVAL ($intervalInHours * $numberOfIntervals) HOUR) AND '$fromDate' GROUP BY FLOOR(TIMESTAMPDIFF(HOUR, created, '$fromDate') / $intervalInHours)";
I'd add another column that is the date(not time) and then use MySQL "group by" to get the most recent for each date.
http://www.tizag.com/mysqlTutorial/mysqlgroupby.php/
This tutorial does just that, but by product type instead of date. This should help!
Do you want all of the events within the 10 days, or just one event per day within the 10 day period?
Either way, consider MySQL's date functions for assistance. It should help you get the date range you want.
Here's one that will get you the first event of the day for the last 10 days.
SELECT *
FROM eventos
WHERE created BETWEEN DATE_SUB(DATE(NOW()), INTERVAL 10 DAY) AND DATE_ADD(DATE(NOW()), INTERVAL 1 DAY)
GROUP BY DATE(created)
ORDER BY MAX(created) DESC
LIMIT 10
Try this:
SELECT *
FROM eventos
WHERE created BETWEEN DATE_SUB(DATE(NOW()), INTERVAL 10 DAY) AND DATE_ADD(DATE(NOW()), INTERVAL 1 DAY)
ORDER BY created DESC
LIMIT 10
I have a user table, where users need to be approved, i want to show users who are not approved and is registered more than 7 days ago.
My user_regdate is a timestamp created with php time() function.
This is what i try, it does not works:
mysql_query("select * from users WHERE user_regdate < now() - interval 7 day AND approved='0' order by id;");
Thanks
PHP's timstamps are a simple integer, whereas MySQL's now() returns a datetime value. Most likely this will fix up the query:
SELECT ... WHERE user_regdate < unix_timestamp(now() - interval 7 day)) ...
Basically, without the unix_timstamp() call, you're comparing apples and oranges.
Primitive solution at best, but im not the best at MySQL time calculation
$timestamp = strtotime("-7 days");
mysql_query("SELECT * FROM users WHERE user_regdate < $timestamp AND approved = 0 ORDER BY id");
php's time() function outputs a unix timestamp (the number of seconds since January 1 1970). MySQL's now() function outputs a formatted date (like 2011-6-9 12:45:34)... so I don't think you can compare them like that.
Try using the unix timestamp, minus 7 days, instead of now() in your query:
$7_days_ago = time() - (7 * 24 * 60 * 60);
mysql_query("select * from users WHERE user_regdate <" . $7_days_ago . " AND approved='0' order by id;");
Try this;
select *
from users
WHERE DATE_SUB(user_regdate,INTERVAL 7 DAY)
AND approved='0'
order by id;
I'm trying to create a custom query that will show the number of stories that have been posted in the last 24 hours on a Drupal 6 site.
Stories are stored in the "node" table. each record has a "created" row that records the UNIX timestamp when the story was posted.
Here's the query I'm trying so far:
$sq = 'SELECT COUNT(*) cnt '
. 'FROM {node} c WHERE created >= dateadd(hour,-24,getdate())';
This doesn't appear to be working though. What am I doing wrong?
EDIT: Here's the overall code I'm trying to use right now:
$sq = 'SELECT COUNT(*) AS cnt FROM {NODE} n WHERE FROM_UNIXTIME(n.created) >= DATE_SUB(NOW(), INTERVAL 1 DAY)';
$q = db_query($sq);
while ($o = db_fetch_object($q)) {
print_r($o);
}
That print_r isn't returning anything. Where's my error?
For MySQL, use:
SELECT COUNT(*) AS cnt
FROM NODE n
WHERE FROM_UNIXTIME(n.created) >= DATE_SUB(NOW(), INTERVAL 1 DAY)
Mind that NOW() includes the time when the statement is run. If you want to count records, starting from midnight of the previous day, use:
SELECT COUNT(*) AS cnt
FROM NODE n
WHERE FROM_UNIXTIME(n.created) >= DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY)
Reference:
FROM_UNIXTIME
DATE_SUB
Since you are doing this in PHP, you can just use $_SERVER['REQUEST_TIME']. My guess is that it will be faster than doing date manipulations with SQL:
$count = db_result(db_query("SELECT COUNT(nid) FROM {node}
WHERE created >= %d;", $_SERVER['REQUEST_TIME'] - 86400));
Alternative you could use time to get the current timestamp, but that will be a tiny bit slower than using the $_SERVER['REQUEST_TIME'] variable.