How to get standard deviation of grouped rows? - php

I want to calculate the standard deviation between page views on my site. I'd like to do this using pure MySQL - without querying the whole table to the webserver - and return a single number to the PHP code for further use. Each page view is stored as a visitor_id - page_id - visit_count trio as per the following schema:
+============+=========+=============+
| visitor_id | page_id | visit_count |
+============+=========+=============+
| 1 | 2 | 7 |
+------------+---------+-------------+
| 2 | 2 | 4 |
+------------+---------+-------------+
| 1 | 1 | 17 |
+------------+---------+-------------+
| 3 | 2 | 12 |
+------------+---------+-------------+
| 1 | 3 | 639478 |
+------------+---------+-------------+
| 2 | 1 | 6 |
+------------+---------+-------------+
page_id refers to a PRIMARY_KEY in the pages table, visitor_id refers to a PRIMARY_KEY in the visitors table. The above table's primary key is the visitor_id - page_id pair, since the same page seen by the same visitor is recorded by increasing the visit_count of the corresponding row, instead of creating a new one.
Before calculating standard deviation, the entries should be grouped together by page_id, their visit_count summed (visitor_id can be ignored here), so, effectively, I want to calculate the deviation of the following:
+=========+=============+
| page_id | visit_count |
+=========+=============+
| 2 | 23 |
+---------+-------------+
| 1 | 23 |
+---------+-------------+
| 3 | 639478 |
+---------+-------------+
I'm aware of the possible PHP solutions, but I'm interested in a MySQL one.

If you want the standard deviation for each page (i.e., the visitors are the population):
select page_id, sum(visit_count) as visit_count, std(visit_count) as visit_std
from table1
group by page_id;
If you want the standard deviation over the pages:
select std(visit_count) as page_std
from (select page_id, sum(visit_count) as visit_count
from table1
group by page_id
) t;

You could create a new table that stores timestamp + current views so you can view a history of changes in views. You'd be able to check the last two timestamped entries and how much the difference is between the two as well as a whole bunch of other stuff you haven't even thought of yet. Like graphs. Or pie charts showing activity increases per week day. Mmmm pie.

Related

Select MySQL return table header as well table body in one query

Hello I am facing hard time trying to realized this task. The problem is that I am not sure in which way this have to be proceeded and couldn't find tutorials or information about realizing this type of task.
The question is I have 2 tables and one connecting table between the two of them. With regular query usually what is displayed is the table header which is known value and them then data. In My case I have to display the table horizontally and vertically since the header value is unknown value.
Here is example of the DB
Clients:
+--------+------ +
| ID | client|
+--------+------ +
| 1 | Sony |
| 2 | Dell |
+--------+------ +
Users:
+--------+---------+------------+
| ID | name | department |
+--------+--------+-------------+
| 1 | John | 1|
| 2 | Dave | 2|
| 3 | Michael| 1|
| 4 | Rich | 3|
+--------+--------+-------------+
Time:
+--------+------+---------------------+------------+
| ID | user | clientid | time | date |
+--------+------+---------------------+------------+
| 1 | 1 | 1 | 01:00:00 | 2017-01-02 |
| 2 | 2 | 2 | 02:00:00 | 2017-01-02 |
| 3 | 1 | 2 | 04:00:00 | 2017-02-02 | -> Result Not Selected since date is different
| 4 | 4 | 1 | 02:00:00 | 2017-01-02 |
| 5 | 1 | 1 | 02:00:00 | 2017-01-02 |
+--------+------+---------------------+------------+
Result Table
+------------+--------+-----------+---------+----------+
| Client | John | Michael | Rich | Dave |
+------------+--------+-----------+---------+----------+
| Sony |3:00:00 | 0 | 2:00:00 | 0 |
+------------+--------+-----------+---------+----------+
| Dell | 0 | 0 | 0 | 2:00:00 |
+------------+--------+-----------+---------+----------+
First table Clients Contains information about clients.
Second table Users Contains information about users
Third Table Time contains rows of time for each users dedicated to different clients from the clients table.
So my goal is to make a SQL Query which will show the Result table. In other words it will select sum of hours which every user have completed for certain client. The number of clients and users is unknown. So first thing that have to be done is Select all users, no matter if they have hours completed or not. After that have to select each client and the sum of hours for each client which was realized for individual user.
The problem is I don't know how to approach this situation. Do I have first to make one query slecting all users then foreach them in the table header and then realize second query selecting the hours and foreaching the body conent, or this can be made with single query which will render the whole table.
The filters for select command are:
WHERE MONTH(`date`) = '$month'
AND YEAR(`date`) ='$year'
AND u.department = '$department'
Selecting single row for tume SUM is:
(SELECT SUM( TIME_TO_SEC( `time` ) ) FROM Time tm
WHERE tm.clientid = c.id AND MONTH(`date`) = '$month' AND YEAR(`date`) ='$year'
This is the query to select the times for a user , here by my logic this might be transformed with GROUP BY c.id (client id), and the problem is that it have to contains another WHERE clause which will specify the USER which is unknown. If the users was known value was for example 5, there is no problem to make 5 subsequent for each user WHERE u.id = 1, 2, 3 etc.
So here are the 2 major problems how to display in same query The users header and them select the sum of hours for each client corresponding the user.
Check out the result table hope to make the things clear.
Any suggestion or answer which can come to resolve this situation will be very helpful.
Thank you!

page views and page like count by date wise for the particular page php mysql

i want to store views and like counts for the particular page .
im using page url is the unique key (index.php),
in my table i have the following columns
common table
id | page name | views | likes | timestamp
1 | index.php | 5 | 3 | 6-2-2014
2 | abount.php | 15 | 77 | 6-2-2014
for views table
id | page name | date | ip
1 | index.php | 6-2-2014 | 127.0.0.1
2 | index.php | 6-2-2014 | 127.0.0.2
3 | index.php | 6-2-2014 | 127.0.0.3
4 | index.php | 6-2-2014 | 127.0.0.4
5 | index.php | 6-2-2014 | 127.0.0.5
for like table
id | page name | date | ip
1 | index.php | 6-2-2014 | 127.0.0.1
2 | index.php | 6-2-2014 | 127.0.0.2
3 | index.php | 6-2-2014 | 127.0.0.3
what im did here means , every time i insert new record in count table i increase the count for particular page in the common table ,
1) Here i allowed only one time to like particular page from one IP.
2) i need to know how i get daily views and likes reports .
I know i have maintaining complicated tables , any simplification for this approach
sorry for my english
The comments about creating a foreign key for the page_id are good and you should look at those. However, your question was about how to get daily summary reports.
This will give you daily views (the same will apply for likes):
SELECT page_name, date, COUNT(ip) as viewcount
FROM views
GROUP BY page_name, date
ORDER BY page_name, date -- you can select any ordering...

MySQL Insert or Replace

I wanted to create a system to track the progress of a player in a game. Each player can be a member of multiple groups, which all have other requirements. In order to track his progress, the stats of the player will be saved once he joins a group. Every time he reloads his stats, the current ones should be saved inside the database.
All stats of the player are stored in a json-format, which will then be parsed either by PHP or JS. An entry with compare = 0 is set once the player joins a group. An entry with compare = 1 should be created the first time a player clicks on Update Stats and from then on it should only be updated, not newly created.
Now my question is: How to achieve that? When reading through the syntax of INSERT INTO I got the following:
INSERT INTO `groups` (`grp`, `id`, `json`, `compare`) VALUES
($grp, $id, $json, 1) ON DUPLICATE KEY SET `json` = $json
However, since there is no key set, and I don't know if I can set up two/three keys (as there can be multiple groups per user, as well as the compare = 0 entry in the same group), I don't think I can do it this way.
+------+----+---------+---------+
| grp | id | json | compare |
+------+----+---------+---------+
| 1 | 1 | stats | 0 |
| 1 | 1 | stats | 1 |
| 1 | 2 | stats | 0 |
| 1 | 2 | stats | 1 |
| 2 | 2 | stats | 0 |
| 2 | 3 | stats | 0 |
| 2 | 3 | stats | 1 |
| 2 | 4 | stats | 0 |
| 2 | 5 | stats | 0 |
+------+----+---------+---------+
grp is the group of the player. There is no real limit set to the
number of groups a player can be in.
id is the ID of the player.
json contains the stats of the player in a json
format (number of points, etc).
compare is a boolean. 0 stands for entry stats (the number of points a player
already had when he registered) and 1 stands for the current stats - Which will
be compared to the entry stats, in order to get the difference (= the points a
player made since joining the group).
I hope my explanation was understandable and someone can help me out.
You can use insert raplace:
REPLACE INTO groups (`grp`, `id`, `json`, `compare`) VALUES (...);
But you must have primary key in table. Replace into automaticly finds out primary key and if record exists, it update row, but if doesn't, it add new row.
You can create a unique key with multiple columns. This will trigger the 'on duplicate' clause.
ALTER TABLE groups
ADD UNIQUE (grp, id, compare)

mysql select data when one field may or may not contain values

Have a MYSQL look up table that returns the points received for a certain place(P) among a number of finishers(N), with a variety of formats(points_id). Different point structures are used for different events. Some times the points awarded depend on the number of finishers(N) Sometimes they don't.
Here is a short version of the table, with two sample structures.
points_id -1 the points depends on N Point_id -2 the points don't.
points
points_id | P | N | points |
1 | 1 | 3 | 90 |
1 | 1 | 2 | 85 |
1 | 1 | 1 | 80 |
1 | 2 | 3 | 60 |
1 | 2 | 2 | 50 |
1 | 3 | 3 | 30 |
3 | 1 | | 100 |
3 | 2 | | 90 |
3 | 3 | | 80 |
3 | 3 | | 70 |
So my question:
1) is there a way to put the wildcard in the table data.
eg if the N column that shows blank had a % in it
and I did this query.
SELECT points from t1 WHERE points_id=3 and P=3 and N=2
It would return 96??
PS I know this doesn't work but is shows my idea.
2) I want it to be fast, may put it in a procedure to use in larger queries. I am guessing unless there is a very simple way to do what I show above. the fastest method will be to have rows for all of the different N's in the points_id =3 case. Is that true?
You might consider UNION ALL:
SELECT points from t1 WHERE points_id=3 AND P=3
UNION ALL
SELECT points from t1 WHERE points_id=3 AND N=2
This will get the results regardless if P=3 or N=2. I copied your database schema and tried this, and it produced:
points
------
80
70
If you do want this to be fast with a large amount of data--you'll really want to have an index and/or primary key.
Try this :
SELECT points from t1 WHERE points_id=3 and P=3 and (N=2 OR (IFNULL(N,'')=''))
// dataType of N varchar
SELECT points from t1 WHERE points_id=3 and P=3 and (N=2 OR (IFNULL(N,0)=0))
// dataType of N numeric type
Let me know if there is any change or am getting you wrong

Reflecting counts in a table to a field (MySQL)

liked_table
-----------
user_id | topic | liked
2 | 3 | 1
3 | 3 | 1
5 | 3 | -1
topics_table
------------
topic_id | likes
3 | count(liked field from liked_table where topic from liked_table is this row's topic_id)
Can I write a formula like this in MySQL like we do in Excel?
Rather than have a table with calculated values you can create a View and have calculated columns in the view. (Accessing data in the view is for the most part identical to a doing the same with an actual table).
MySQL View Documentation

Categories