Question

I need to provide the following data regarding member logins as an example:

LAST HOUR 654
LAST DAY 15,648
LAST WEEK 109,536
LAST MONTH 460,051
LAST YEAR 5,520,614

I am wondering what could be the best possible structure of a table to hold this information in MySQL DB.

Currently I'm thinking of just storing:

user datetime

I expect this would get very large over time and become slow to query.

Is there a better way to structure a table to get the information on logins - hourly, day, week, month, year etc?

Was it helpful?

Solution

$current_time = strtotime(date('d-M-Y g:i:s A'));

$last_hour = $current_time - 3600;
$last_day = $current_time - (3600*24);
$last_week = strtotime("-1 week");
$last_month = strtotime("-1 month");
$last_year = strtotime("-1 year");

// now count

// count for last hour
$sql = "SELECT COUNT(user_id) AS cnt FROM `your_table` WHERE datetime>='$last_hour' ";

// count for last day
$sql = "SELECT COUNT(user_id) AS cnt FROM `your_table` WHERE datetime>='$last_day' ";

// count for last week
$sql = "SELECT COUNT(user_id) AS cnt FROM `your_table` WHERE datetime>='$last_week' ";

// count for last month
$sql = "SELECT COUNT(user_id) AS cnt FROM `your_table` WHERE datetime>='$last_month' ";

// count for last year
$sql = "SELECT COUNT(user_id) AS cnt FROM `your_table` WHERE datetime>='$last_year' ";

OTHER TIPS

Having user information repeated at every row in the log table is very bad, look at Normalizing your database

  1. Create a user table with a unique ID
  2. Create the logs table, instead of user in that table, put a reference to the user by that user's ID.

You can also use a timestamp value and have MySQL initialize/auto-set the field when the row is added

So your structure may look like:

user_tbl
 - uid (int)
 - name
 - datax
 - etc

log_tbl
 - uid (int)
 - login_time (datetime/timestamp)

Now to get information on the login, depending on which language you're using, you can parse the timestamp. In PHP:

$time = // timestamp value from database

using PHP date() function

$date = date('m/d/Y', $time);

Other Values

$year = $time/31556926 % 12; // to get year
$week = $time / 604800 % 52; // to get weeks
$hour = $time / 3600 % 24; // to get hours
$minute = $time / 60 % 60; // to get minutes
$second = $time % 60; // to get seconds

I would do it like you suggest, just user and a datetime field (not called datetime). Put a default of CURRENT_TIMESTAMP for the datetime. You can archive or partition data based on datetime, but MySQL will handle millions of rows no problem. Put an index on the datetime field. Then use views to do your counts, like this:

SELECT COUNT(YEAR(testcol)) AS CNT FROM test.test;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top