简体   繁体   中英

MySQL Counting Results Within a Range and First Occurance In Any Range

Looking for some advice on the best way to accomplish this. I've tried Unions, Joins, and Alias examples from a few Stack Overflow questions - none seems to get me where I want to go to no fault of theirs. I think I've just been looking to solve this the wrong way.

I've got one table that logs all activity from our users. Each log contains a column with an ID and another with a TIMESTAMP. There is no column that states what the event type is.

What I'm looking to do is grab counts within a range and append a virtual column with the activation date (first access) regardless if it is in the range or not. The business case for this is that I'd like to have reports that show users active within a range, their activation date, and the amount of events in the range.

The HTML output of this would look like this: User / Total Visits in the Range / First Visit (in the range or not) / Most Recent Visit (in the range)

How I've gotten this far is by doing this:

$result = mysql_query("
SELECT user, MIN(timestamp), MAX(timestamp), count(user) 
AS tagCount FROM " . $table . " 
WHERE date(timestamp) BETWEEN '" . $startdate . "' AND '" . $enddate . "'
GROUP BY user 
ORDER BY " . $orderby . " " . $order) or die(mysql_error()); 

I then loop:

$i = 1;
while($row = mysql_fetch_array($result)){
    $user_name = str_replace("www.", "", $row['user']);  // removing www from usernames
        if( $i % 2 != 0) // used for alternating row colors
            $iclass = "row";
        else
            $iclass = "row-bg";
         echo  "<div class=\"" . $iclass . "\"><div class=\"number\">" . $i . "</div><div class=\"number\">" . $row['tagCount'] . "</div><div class=\"name\">" . "<a href=\"http://" . $row['user'] . "\" target=\"_blank\">"  . $server_name . "</a>" . "</div>" . "<div class=\"first\">" . $row['MIN(timestamp)'] . "</div><div class=\"recent\">" . $row['MAX(timestamp)'] . "</div></div>";    
                    $i++;
        }

The MIN(timestamp) in the above grabs the first timestamp in the range - I want to grab the first timestamp regardless of range.

How can I do this?

The key is to create a virtual derived table that calculates their first access separately and then join to it from your query that returns records for the time period you specify.

The below is SQL Server code, but I think it's fine in mysql too. If not, let me know and i'll edit the syntax. The concept is sound either way though.

Just setup code for the sample

if object_id('tempdb..#eventlog') is not null
     drop table #eventlog


create table #eventlog
(
    userid int ,
    eventtimestamp datetime
)

insert #eventlog
select 1,'2011-02-15'
UNION
select 1,'2011-02-16'
UNION
select 1,'2011-02-17'
UNION
select 2,'2011-04-18'
UNION
select 2,'2011-04-20'
UNION
select 2,'2011-04-21'

declare @StartDate datetime
declare @EndDate datetime

set @StartDate = '02-16-2011'
set @EndDate = '05-16-2011'

Here's the code that would solve your problem, you can replace #eventlog with your tablename

select e.userid,
        min(eventtimestamp)as FirstVisitInRange,
        max(eventtimestamp) as MostRecentVisitInRange,
        min(e2.FirstAccess) as FirstAccessEver,
        count(e.userid) as EventCountInRange
from #eventlog e 
        inner join 
            (select userid,min(eventtimestamp) as FirstAccess
                  from #eventlog
                group by userid
              ) e2 on e.userid = e2.userid
   where 
          e.eventtimestamp between @StartDate and @EndDate
   group by e.userid

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM