Best way to update view count in PHP/MySQL - php

My client has a table that tracks total views for each of his articles. The problem is they want me to break the view count into days. I can easily enough query the db and grab the view counts, but I'm unsure of how to grab each days view count (for each article of course).
In case I'm not being clear (which is usually the case I've been told) I have a field in a table that collects all views on each article with no regard to date or time. If the article was viewed, the row is plus one'd. Look at the record a year from now and the view count shows 2,000. That's it.
What I want to do is capture each days view count for each article and plunk that into its own table but I CANNOT impact said view count field/record. This way, the client can view each days view count on each article. Any idea on the best approach?
I hope that all made sense!!

If I were you I would make a new table for views and insert a new record on each view and when was it viewed, then I would select all the views that are dated today and count them and that would give me the number of times the article was viewed today and it would still keep the total count

Something like:
INSERT INTO `daily_views` SET `views` =
SELECT COUNT(*) FROM `views_table`
WHERE `date` BETWEEN '2013-06-10'
AND '2013-06-11'
AND `post_id` = 1
, `post_id` = 1;

Start at New Year Eve. Each day take the count and store it in a separate table. On the next day subtract current count with the stored one - this is yesterday's count - store the difference on another table together with the date. So, clear or not?

Related

What is the correct and most efficient approach for data ranking/ordering

I am trying to wrap my head around a ranking feature for wordpress posts.
I have a Custom Post Type with thousands of posts. Each one of these posts has meta data called score (which is numerical). I want to have a ranking for all these posts based on the score value. Thus post_id and score are the two values I am looking for. The rank position of posts will be used in various places of my site.
Now what would be the correct and most efficient way to do this? Should I:
Just get all the post_ids and scores and store them in an array. Sort the array by score and get me the position of the desired postID in the array, which is the rank.
Create a separate table, fill it with the post_id and score sets and then sort the table. Update this table every time the score changes in a post and resort.
Create a separate table, fill it with the post_id and score sets and sort the table. Only update it periodically (like every 30 minutes) to hold the load down?
What I need this for is to have the score display in each post and also have a ranking widget use the ranking data. So it would be great if the data is always up to date (post score adjusted -> rank update). But if this is going to create a heavy load on the database/server I would be also fine if the data is not really up to date, but X minutes old.
As I am pretty new to databases I have a hard time figuring out what loads different approaches will create. Would be great if anyone could poke me in the right direction.
Since ranking is not static process, it needs to be updated everytime there is an insert or an update into you table
I would recommend you to handle that in query like :
SELECT #rownum:=#rownum + 1 as row_number,
t.*
FROM (
< your ordered query goes here >
) t,
(SELECT #rownum := 0) r

Tracking Play Count over Multiple Months

I have a page written in PHP that has a playlist of songs. When a user listens to a song I have some javascript run some PHP to update a field in the MySQL database that increments a 'play count' number.
This is good for a running total of how many times a song was listened to, but I was wondering if anyone had any suggestions for how to get it so I could easily break down by month or by week the play count of a particular song.
You would need to add a table to your database that would track the timestamp, song, and user. You should still keep the play count number in the users table for easier querying. But if you want to break down number of plays by date you'll need the other table.
Something like
user_plays
----------
play_id
user_id
song_id
date_played
Then you can run a query on that table to get a count of number of plays for a date range.
For a user:
SELECT COUNT(play_id) as num_plays
FROM user_plays
WHERE user_id = ? AND date_played BETWEEN ? AND ?
For a song:
SELECT COUNT(play_id) as num_plays
FROM user_plays
WHERE song_id = ? AND date_played BETWEEN ? AND ?
You'll need to store more details than just a total play count. I'd introduce an additional table to record all of the playback events, storing the ID of the track and the timestamp. Then you can query this table for all of the plays relating to a particular track between whatever dates.
Obviously querying a huge table like that is something you'll want to cache.

How to generate statistics on article views last week

I see on sites that they sometimes have a statistic showing how many views an article or downloads a file had over the last week. I think download.com does something like this. I was wondering how they go about doing this. Are they actually keeping track of every days downloads or am I missing something really basic?
Are they doing something like having three rows called total_downloads, last_week_downloads, this_week_downloads. Then every week, copying the value of this_week_downloads to last_week_downloads and then resetting this_week_downloads to 0?
There are a couple of ways to do it, depending on what your trying to get out of the stats.
One way is to include a visits column on your table, then just increase that number by 1 each time that article's page is loaded.
This however isn't very good for giving the past weeks number of views. You can do this in 2 ways:
1) another column in your table doing the same as visits, but run a cron job to put it back to 0 every week.
2) create another table which holds article_id, ip_address and timestamp, you would insert a record each time someone visits the article, storing their IP address (allowing you to roughly get page views and unique page views), and of course the timestamp allows you to query for only a sub-set of those records. Note: using this method you could store more information for stats, but it does require a lot more server resources.
The most basic way you can do this is associate a MySQL field alongside your article on the database and just increment it.
Assuming you we're retreiving article 123 from your database you would have something like this on your code:
<?php
// this would increment the number of views
$sql = "UPDATE table SET count_field=count_field+1 WHERE id=123";
...
?>

Daily/Weekly/Monthly Highscores

I have an online highscores made with php + mysql but it currently shows the All Time highscores, I want to add Daily/Weekly/Monthly to that and I was wondering what would be the best way todo that?
My current thought is to add 3 new tables and then have the data inserted into each of them, and then having a cron which would run at the appropriate times to delete the data from each of the tables.
Is there any better way I could do this?
Another thing, I want to have it so the page would be highscores.php?t=all t=daily, etc. How would I make it so that the page changed the query depending on that value?
Thanks.
Use one table and add a column with the date of the highscore. Then have three different queries for each timespan, e.g.
SELECT ... FROM highscores WHERE date>"05-12-2011";
If you want to have a generic version without the need to have a fixed date, use this one:
SELECT ...
FROM highscores
WHERE date >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY;

Is there a better way to get old data?

Say you've got a database like this:
books
-----
id
name
And you wanted to get the total number of books in the database, easiest possible sql:
"select count(id) from books"
But now you want to get the total number of books last month...
Edit: but some of the books have been
deleted from the table since last month
Well obviously you cant total for a month thats already past - the "books" table is always current and some of the records have already been deleted
My approach was to run a cron job (or scheduled task) at the end of the month and store the total in another table, called report_data, but this seems clunky. Any better ideas?
Add a default column that has the value GETDATE(), call it "DateAdded". Then you can query between any two dates to find out how many books there were during that date period or you can just specify one date to find out how many books there were before a certain date (all the way into history).
Per comment: You should not delete, you should soft delete.
I agree with JP, do a soft delete/logical delete. For the one extra AND statement per query it makes everything a lot easier. Plus, you never lose data.
Granted, if extreme size becomes an issue, then yeah, you'll potentially have to start physically moving/removing rows.
My approach was to run a cron job (or scheduled task) at the end of the month and store the total in another table, called report_data, but this seems clunky.
I have used this method to collect and store historical data. It was simpler than a soft-delete solution because:
The "report_data" table is very easy to generate reports/graphs from
You don't have to implement special soft-delete code for anything that needs to delete a book
You don't have to add "and active = 1" to the end of every query that selects from the books table
Because the code to do the historical reporting is isolated from everything else that uses books, this was actually the less clunky solution.
If you needed data from the previous month then you should not have deleted the old data. Instead you can have a "logical delete."
I would add a status field and some dates to the table.
books
_____
id
bookname
date_added
date_deleted
status (active/deleted)
From there you would be able to query:
SELECT count(id) FROM books WHERE date_added <= '06/30/2009' AND status = 'active'
NOTE: It my not be the best schema, but you get the idea... ;)
If changing the schema of the tables is too much work I would add triggers that would track the changes. With this approach you can track all kinds of things like date added, date deleted etc.
Looking at your problem and the reluctance in changing the schema and the code, I would suggest you to go with your idea of counting the books at the end of each month and storing the count for the month in another table. You can use database scheduler to invoke a SP to do this.
You have just taken a baby step down the road of history databases or data warehousing.
A data warehouse typically stores data about the way things were in a format such that later data will be added to current data instead of superceding current data. There is a lot to learn about data warehousing. If you are headed down that road in a serious way, I suggest a book by Ralph Kimball or Bill Inmon. I prefer Kimball.
Here's the websites: http://www.ralphkimball.com/
http://www.inmoncif.com/home/
If, on the other hand, your first step into this territory is the only step you plan to take, your proposed solution is good enough.
The only way to do what you want is to add a column to the books table "date_added". Then you could run a query like
select count(id) from books where date_added <= '06/30/2009';

Categories