In my database I have a column called featured it is of type datetime and the default value is current-timestamp
Now i want to find all rows where the featured date is greater than now, should be simple enough using this
$sql = "SELECT id FROM `directory` WHERE category LIKE '%$cat%' AND LOWER(`town`)=LOWER('$city') AND `featured` > NOW() ORDER BY dateadded DESC";
But if I make a new entry in the db, those new entries are returned by above sql even though those would have featured date a few seconds before "now".
So I tried
$sql = "SELECT id FROM `directory` WHERE category LIKE '%$cat%' AND LOWER(`town`)=LOWER('$city') AND `featured` > NOW() + INTERVAL 6 HOUR ORDER BY dateadded DESC";
This worked, but now it doesnt work, i increased it to 48 hours and now it works again
but really
`featured` > NOW()
Should be enough because when i use this sql all values in the db would be in the past even if just by a few seconds, so why is this
I want to check if the user has 5 records in my MySQL database in the last hour. That´s how I am doing it now:
$link = mysqli_query($link, "SELECT * FROM find_points WHERE timestamp > '.time()-3600.' AND user_id = '1' ORDER BY id DESC");
if(mysqli_num_rows($link) >= 5) {
echo 'more than 5 results';
}
It looks like it should work, but it doesn't work...
Please use below query
SELECT * FROM find_points WHERE TIMESTAMPDIFF( hour, timestamp , now() ) > 1 AND user_id = '1' ORDER BY id DESC
You can read in manual about TimestampDiff
It can be used to run difference between 2 dates in various formats.
Please check the Demo on SqlFiddle
It shows how TimestampDiff returns result and you can use the same in WHERE clause.
Update
Based on your comment, that the timestamp is stored as Unix Timestamp, you could use the following query:
SELECT * FROM find_points WHERE TIMESTAMPDIFF( hour, FROM_UNIXTIME(timestamp) , now() ) > 1 AND user_id = '1' ORDER BY id DESC
FROM_UNIXTIME will convert your UNIX Timestamp to DateTime Format. You can then pass this to TIMESTAMPDIFF which will calculate difference and return the number of hours.
Hope this helps.
"SELECT * FROM find_points WHERE timestamp > DATE_ADD(NOW(), INTERVAL 1 HOUR) AND user_id = '1' ORDER BY id DESC"
if the user in the 5 hours has more calls in the past 10 hours, then he should tell me as an example "true". If not, he should say false to me.
if($aufruf = $pdo->prepare("
SELECT
profil_aufrufe.id,
profil_aufrufe.user_id,
profil_aufrufe.aufrufer_id,
profil_aufrufe.date
FROM
profil_aufrufe
WHERE
profil_aufrufe.user_id = :user_id AND profil_aufrufe.date ..."
))
I thought for a long time, but found no way how I can write the SQL code.
Here is your code
if($aufruf = $pdo->prepare("
SELECT
profil_aufrufe.id,
profil_aufrufe.user_id,
profil_aufrufe.aufrufer_id,
profil_aufrufe.date
FROM
profil_aufrufe
WHERE
profil_aufrufe.user_id = :user_id AND profil_aufrufe.date ..."
))
first of all you can't take a column date in your mysql table its reserved keyword of mysql
date
and why are you using alias whenever you don't join any table, there is no need of alias i simplify it i change column date to cdate
if($aufruf = $pdo->prepare("
SELECT
id,
user_id,
aufrufer_id,
cdate
FROM
profil_aufrufe
WHERE
user_id = :user_id AND
cdate between DATE_SUB(NOW(),INTERVAL 5 HOUR) and DATE_SUB(NOW(), INTERVAL 10 HOUR) "));
I think this will work for you
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
Im having a little trouble constructing a query.
I have a table with 3 columns.
id - day - pageviews
What i basically want to do is get 8 id's from the table where the pageviews are the highest from the last 60 days.
The day column is a datetime mysql type.
Any help would be great, im having a little trouble figuring this one out.
Cheers,
Almost the same as TuteC posted, but you'll need a group by to get what you need...
SELECT id, SUM(pageviews) totalViews
FROM table
WHERE DATE_SUB(CURDATE(), INTERVAL 60 DAY) <= day
GROUP BY id
ORDER BY totalViews DESC
LIMIT 8
Do something like this:
SELECT id FROM table_name
WHERE DATE_SUB(CURDATE(),INTERVAL 60 DAY) <= day
ORDER BY pageviews DESC
LIMIT 8;
$sixtyDaysAgo = date('Y-m-d',strtotime('-60 days'));
$sql = "SELECT id
FROM table_name
WHERE day >= '$sixtyDaysAgo 00:00:00'
ORDER BY pageviews DESC
LIMIT 8";
If each row is a number of pageviews for that day, and you're looking for the highest total sum of 60 days' worth, then you'll need to total them all and then grab the top 8 from among those totals, like so:
$sql = "SELECT id
FROM (
SELECT id, SUM(pageviews) AS total_pageviews
FROM table_name
WHERE day >= '$sixtyDaysAgo 00:00:00'
GROUP BY id
) AS subselect
ORDER BY total_pageviews DESC
LIMIT 8";