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
Related
I have a database with the rows: SearchTerm | userId | date | historyId
I need to get the amount of entries every hour in the last 24 hour period where the userId=userid.
So far I have as follows:
$stmt = $conn->prepare("SELECT historyId FROM webHistory WHERE date >= now() - INTERVAL 1 DAY GROUP BY HOUR(date) AND userId=?");
I'm now a little stuck, how would I go about getting the num_rows for each hour group? I though about using count(*), but would this be the right method, if so how would I go about doing this?
Lastly, for mobile displays I would need to group by every two hour period, is this possible as I can only seem to find documentation on HOUR(), possibly DATEPART()?
You just need count(*):
SELECT HOUR(date) as hr, historyId, COUNT(*) as num_rows
FROM webHistory
WHERE date >= now() - INTERVAL 1 DAY AND userId=?
GROUP BY HOUR(date);
The condition on userId goes in the where clause. It is good form to include the hour(date) in the select, so you know which hour a given count refers to.
EDIT:
To just get today's hours, hour can do:
SELECT HOUR(date) as hr, historyId, COUNT(*) as num_rows
FROM webHistory
WHERE date(date) = date(now()) AND userId=?
GROUP BY HOUR(date);
To list data by two-hour periods:
SELECT FLOOR(HOUR(date)/2) AS period,historyId FROM webHistory, COUNT(*) as num_rows
WHERE date >= now() - INTERVAL 1 DAY
GROUP BY date, period
We can use SQL BETWEEN operator
SELECT HOUR(date) as hr, historyId, COUNT(*) as num_rows
FROM webHistory
WHERE date BETWEEN SUBDATE(date(now()),1) AND date(now())
AND userId=?
GROUP BY HOUR(date);
I have flash games website that allows users to "like" or "dislike" a particular game. When the user selects "like/dislike", my php application inserts a record into a table named likes which contains the following columns:
game_id - (ID of the selected game)
time - (the time of the user action, per the time function in php)
type - (the action type: "like" or "dislike")
How should I fetch the id's of 10 games having the most "likes" ie type ='like', in the last week ie week(time()-60*60*24*7). Then order the results by the greatest number of "likes" per game?
Here is the query I tried using, but it's still not helping. As it only fetches all of the like records, not the totals.
SELECT `game_id`
FROM `likes`
WHERE `type` = 'like'
AND `time` > '{$time}'
// Php
$time = date_sub(now() ,interval 7 day); // Week
// SQL
SELECT `game_id` FROM `likes` WHERE `type` = 'like' AND `time` > '{$time}' LIMIT 10
You may need to play around with date_sub to get it just right, but hopefully this will get you on the right track. The LIMIT 10 will limit it to 10 results, which may be all you needed.
Assuming the time column is a date column you could do this.
$time = date("Y-m-d", time() - (60*60*24*7));
or more concisely
$time = date("Y-m-d", strtotime("one week ago"));
and the query should read
SELECT `game_id`, count(*) as num_likes
FROM `likes`
WHERE `type` = 'like'
AND `time` > '{$time}'
GROUP BY game_id
ORDER BY num_likes desc
LIMIT 10;
You can use:
$timestamp = strtotime("one week ago");
$sql ="SELECT game_id,
COUNT(type) as like_count
FROM likes
WHERE type = 'like' AND `time` > ".$timestamp."
GROUP BY type
ORDER BY like_count DESC
LIMIT 0,10";
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
Using PHP/MySQL
I'm trying to create a select statement that gets the data from the least day of the current week (I'm using it to show data on a certain player 'this week'). The week starts on Sunday. Sundays's data may not always exist therefore if the Sunday data isn't found then it would use the next earliest day found, Monday, Tuesday, etc.
My date column is named 'theDate' and the datatype is 'DATE'
The query would need to be something like:
SELECT *
FROM table_name
WHERE name = '$username'
AND [...theDate = earliest day of data found for the current week week]
LIMIT 1
It would return a single row of data.
This is a query I tried for getting the 'this week' data, It doesn't seem to work correctly on Sunday's it shows nothing:
SELECT *
FROM table_name
WHERE playerName = '$username'
AND YEARWEEK(theDate) = YEARWEEK(CURRENT_DATE)
ORDER BY theDate;
This is the query that I'm using to get 'this months' data and it works even if the first day of the months data is not found, it will use the earliest date of data found in the current month/year (this query works perfect for me):
SELECT *
FROM table_name
WHERE playerName = '$username'
AND theDate >= CAST( DATE_FORMAT( NOW(),'%Y-%m-01') AS DATE)
ORDER BY theDate
LIMIT 1
Without trying this, you probably need an inner query:
select *
from table_name tn
where tn.the_date =
(select min(the_date)
from table_name
where WEEKOFYEAR(the_date) = WEEKOFYEAR(CURDATE())
and YEAR(the_date) = YEAR(CURDATE()))
viz, give me the row(s) in the table with a date equal to the earliest date in the table in the current week and year.
Try this
SELECT * FROM table_name WHERE name = '$username'
AND your_data IS NOT NULL
AND WEEK(the_date,0 = WEEK(NOW(),0))
ORDER BY DATE_FORMAT(the_date,'%w') ASC
Try the following, replace YOUR_DATE with the date from the column you want (theDate):
SELECT ADDDATE(YOUR_DATE, INTERVAL 1-DAYOFWEEK(YOUR_DATE) DAY)
FirstDay from dual
Did you try:
SELECT ADDDATE(theDate , INTERVAL 1-DAYOFWEEK(theDate ) DAY) FirstDay
FROM table_name
WHERE playerName = '$username'
ORDER BY theDate DESC
LIMIT 1
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";