Organizing member join dates/member growth data into graphable chunks - php

I'm dabbling with pChart and would like to start with a simple line graph showing the growth in membership over time.
Y-axis would be # of membersX-axis would be time
For each time datapoint, I need a corresponding total members datapoint.
My user table is structured as:
[user_id] [join_date]
The approach I came up with on the bus to work this morning is:
$Q = " SELECT MONTH(join_date), DAY(join_date), COUNT(user_id)"
. " FROM user_basic_data GROUP BY join_date";
$R = mysql_query($Q);
$dateS = '';
$totalS = '';
$c = 0; // total members counter
while ($row = mysql_fetch_row($R)) {
$dateS .= $row[0].'-'.$row[1].','; // month-day,month-day,month-day
$c = $row[2] + $c; // new total for new date
$totalS .= $c.','; // total1,total2,total3
}
// trim trailing commas
$dateS = substr($dateS, 0, -1);
$totalS = substr($totalS, 0, -1);
echo "<p>$dateS</p>"; // Ex: 8-10,8-15,8-20
echo "<p>$totalS</p>"; // Ex: 12,17,23
Those string formats are how pChart likes the data, and I know the current query would need a year value as well for real use, so please don't get hung up on those points.
I'd like to know if there's a better way to go about getting the changing total members over time. I'm guessing handling it within MySQL would be faster, but I can't think of a way to do that.
Thank you for your time.

To get a running total, use:
SELECT DISTINCT
DATE(ubd.join_date) AS dt,
(SELECT COUNT(*)
FROM user_basic_data t
WHERE DATE(t.join_date) <= DATE(ubd.join_date)) AS num_users
FROM user_basic_data ubd
DATE returns dates as YYYY-MM-DD; If you still want Month-Day - use DATE_FORMAT by replacing the DATE(udb.join_date) with:
DATE_FORMAT(ubd.join_date), '%m-%d')
You don't need the logic to create the comma separated lists in PHP - just need to populate the two variables:
$Q = " SELECT GROUP_CONCAT(x.dt) AS dates,
GROUP_CONCAT(x.num_users) AS totals
FROM (SELECT DISTINCT
DATE(ubd.join_date) AS dt,
(SELECT COUNT(*)
FROM user_basic_data t
WHERE DATE(t.join_date) <= DATE(ubd.join_date)) AS num_users
FROM user_basic_data ubd ) x";
$R = mysql_query($Q);
while ($row = mysql_fetch_row($R)) {
echo "<p>$row[0]</p>"; // Ex: 8-10,8-15,8-20
echo "<p>$row[1]</p>"; // Ex: 12,17,23
}

Related

Pull number of rows from a SQL query and put it in PHP as a variable?

This is 4 queries put into one. This is really old code and once I can make this work we can update it later to PDO for security. What I am trying to do is count rows from
select count(*) from dialogue_employees d_e,
dialogue_leaders d_l where
d_l.leader_group_id = d_e.leader_group_id
and use it in a formula where I also count how many rows from dialogue.status = 1.
The formula is on the bottom to create a percentage total from the results. This is PHP and MySQL and I wasn't sure the best way to count the rows and put them as a variable in php to be used in the formula on the bottom?
function calculate_site_score($start_date, $end_date, $status){
while($rows=mysql_fetch_array($sqls)){
$query = "
SELECT
dialogue.cycle_id,
$completecount = sum(dialogue.status) AS calculation,
$total_employees = count(dialogue_employees AND dialogue_leaders), dialogue_list.*,
FROM dialogue,
(SELECT * FROM dialogue_list WHERE status =1) AS status,
dialogue_employees d_e,
u.fname, u.lname, d_e.*
user u,
dialogue_list,
dialogue_leaders d_l
LEFT JOIN dialogue_list d_list
ON d_e.employee_id = d_list.employee_id,
WHERE
d_l.leader_group_id = d_e.leader_group_id
AND d_l.cycle_id = dialogue.cycle_id
AND u.userID = d_e.employee_id
AND dialogue_list.employee_id
AND site_id='$_SESSION[siteID]'
AND start_date >= '$start_date'
AND start_date <= '$end_date'";
$sqls=mysql_query($query) or die(mysql_error());
}
$sitescore=($completecount/$total_employees)*100;
return round($sitescore,2);
}
If you separate out your queries you will gain more control over your data. You have to be careful what your counting. It's pretty crowded in there.
If you just wanted to clean up your function you can stack your queries like this so they make more sense, that function is very crowded.
function calculate_site_score($start_date, $end_date, $status){
$query="select * from dialogue;";
if ($result = $mysqli->query($query))) {
//iterate your result
$neededElem = $result['elem'];
$query="select * from dialogue_list where status =1 and otherElem = " . $neededElem . ";";
//give it a name other than $sqls, something that makes sense.
$list = $mysqli->query($query);
//iterate list, and parse results for what you need
foreach($list as $k => $v){
//go a level deeper, or calculate, rinse and repeat
}
}
Then do your counts separately.
So it would help if you separate queries each on their own.
Here is a count example How do I count columns of a table

Codeigniter: display two data in query with distinct and count

I'm try to display two data of one query using codeigniter.
$query = "SELECT count(distinct p.id_paciente), count(c.pacientes_id_paciente) FROM paciente p, cita c WHERE p.id_paciente=c.pacientes_id_paciente AND p.usuarios_id_usuario=43 AND p.aseguradoras_id_aseguradora=8 AND c.dia_cita>='2015-04-16' AND c.dia_cita<='2015-04-16'";
$sql = $this->db->query($query);
How can I to show the two results of count(distinct p.id_paciente) and the count(c.pacientes_id_paciente)
I try using
foreach ($sql->result_array() as $row)
{
echo $row['id_paciente'];
echo $row['pacientes_id_paciente'];
}
But only display the content of the array...
Thanks
There are several issues with your code:
Use aliases to name columns in the resultset to be able to address them later by name
SELECT COUNT(distinct p.id_paciente) AS count1, ...
^^^^^^
Don't interpolate query strings yourself. Use Codeigniter's query bindings
This may not be relevant to you but if dia_cita has time component to it (i.e. is of type datetime) you may want to change your WHERE condition to
c.dia_cita >= ? AND c.dia_cita < ? + INTERVAL 1 DAY
There is no need for foreach loop. You always get only one row with this query. Therefore use Codeigniter's row() or row_array().
That being said your code may look like
$sql = "
SELECT COUNT(DISTINCT p.id_paciente) AS count1,
COUNT(c.pacientes_id_paciente) AS count2
FROM paciente p JOIN cita c
ON p.id_paciente = c.pacientes_id_paciente
WHERE p.usuarios_id_usuario = ?
AND p.aseguradoras_id_aseguradora = ?
AND c.dia_cita >= ?
AND c.dia_cita < ? + INTERVAL 1 DAY
";
$bindings = array(43, 8, '2015-04-16', '2015-04-16')
$row = $this->db
->query($sql, $bindings)
->row_array();
echo $row['count1'], $row['count2'];

MySQL/PHP: Multiple AND/OR tags in SELECT from two tables

I've got two tables, customer and reservations. customer and reservations both contain a row called customerID. reservations contains two columns named resStart and resEnd that only have dates in them (YYYY-MM-DD, which is the exact format I'll be using to establish the $todaysdate variable.
I'd like to join those two to produce a table with single column of customerID along with other info, but only if $todaysdate falls on or between two dates. Note: $todaysdate is established elsewhere in my documents as either a _GET from url (ie. day.php?date=2012-07-04) or if none is established, today's date with date('Y-m-d'). This part of the code is not where my problems are lying, I'm sure of that. I'm thinking it's a syntax error somewhere while defining the information in the mySql query.
Here's what I'm working with. A little explanation: I'm wrapping PHP code around Javascript, and the goal here is to produce a separate DIV for each resStart. The Javascript is fetching offset variables to add to the CSS of each DIV, so each DIV is automatically placed relative to the equipment it's representing.
<?php
$getreservations = mysql_query("
SELECT * FROM customer LEFT JOIN reservations WHERE ( customer.customerID = reservations.customerID )
AND ($todaysdate = resStart OR $todaysdate >= resStart AND $todaysdate <= resEnd )
")
or die(mysql_error());
while( false !== ($row = mysql_fetch_assoc($getreservations)))
{
$nameLast = $row["nameLast"];
$nameFirst = $row["nameFirst"];
$customerID = $row["customerID"];
$equipID = $row["equipID"];
$resStart = $row["resStart"];
$resEnd = $row["resEnd"];
$timeStart = $row["timeStart"];
$timeEnd = $row["timeEnd"];
$result = strtotime($timeStart);
$minute = date("i", $result );
$second = date("s",$result );
$hour = date("H", $result );
if(true) {
?>
<script language='javascript'>
var left = $('#<?php echo("$hour$minute");?>').offset().left;
var top = $('#<?php echo $equipID;?>').offset().top;
$(document).ready(function() {
$('#<?php echo ("$customerID$equipID");?>).css( { 'left': (pos.left + width) + 'px', 'top': (pos.top + top) + 'px' } );
}
</script>
<?php }
echo ("<div class='resContainer $customerID$equipID' id=$customerID$equipID>$nameLast, $nameFirst</div> ");
} ?>
SELECT * FROM customer c INNER JOIN reservations r USING(customerID) WHERE '{$todaysdate}' BETWEEN r.resStart AND r.resEnd
However, You can also get the "todaysdate" in SQL: DATE(NOW()), and the statement will be:
SELECT * FROM customer c INNER JOIN reservations r USING(customerID) WHERE DATE(NOW()) BETWEEN r.resStart AND r.resEnd
EDIT: added quotes around $todaysdate variable to avoid confusion
Try your query directly in database first. You'll get proper error code and the information, where the problem is.
When using JOIN, you should specify the join condition, with USING or ON (table1.field=table2.field). (ref to doc: http://dev.mysql.com/doc/refman/5.0/en/join.html)
Try below query:
SELECT * FROM customer
LEFT JOIN reservations on customer.customerID = reservations.customerID
WHERE curdate() BETWEEN r.resStart AND r.resEnd

Total up how many men and how many women in a column. Possibly in order to repopulate the planet

Trying to search through a column in a db, and pull out the total number of males, and total number of females.
This data is stored in the db as f and m in the whatsex column.
$query = "SELECT whatsex, COUNT(*) FROM soberdata GROUP BY whatsex";
$result = mysqli_query($connection,$query) or die(mysql_error());
$sexdb = mysqli_fetch_array($result);
$totalmale = $sexdb['m'];
$totalfemale = $sexdb['f'];
echo $totalfemale." & ".$totalmale;
This code outputs nothing. What am I doing wrong?
$sexdb have only "whatsex" and "COUNT(*)" columns. You should use one of them
try
print_r($sexdb);
and look if some of results meet your needs
Your query is going to return a whatsex value, and a COUNT(*) value, not m or f. Doing a var_dump($sexdb) would show you what's in the array.
You are treating a multi-dimensional array as flat. You could do this to flatten it
$query = "SELECT whatsex, COUNT(*) as total FROM soberdata GROUP BY whatsex";
while ($row = mysqli_fetch_array($result)) {
$$row['whatsex'] = $row['total']; // this makes a variable ($m or $f) using the value of the row
}
$totalmale = !empty($m) ? $m : 0;
$totalfemale = !empty($f) ? $f : 0;
You should empty check the results of the db in case there is no male or female entries to avoid errors.

Help with mysql sum and group query and managing results for jquery graph

I have a system I am trying to design that will retrieve information from a database, so that it can be plotted in a jquery graph. I need to retrieve the information and somehow put it in the necessary coordinates format (for example two coordinates var d = [[1269417600000, 10],[1269504000000, 15]];).
My table that I am selecting from is a table that stores user votes with fields:
points_id (1=vote up, 2=vote down),
user_id,
timestamp, (UNIX TIMESTAMP)
topic_id
What I need to do is select all the votes and somehow group them into respective days and then sum the difference between 1 votes and 2 votes for each day. I then need to somehow display the data in the appropriate plotting format shown earlier. For example April 1, 4 votes. The data needs to be separated by commas, except the last plot entry, so I am not sure how to approach that. I showed an example below of the kind of thing I need but it is not correct,
echo "var d=[";
$query=mysql_query(
"SELECT *, SUM(IF(points_id = \"1\", 1,0))-SUM(IF([points_id = \"2\", 1,0)) AS 'total'
FROM points LEFT JOIN topic ON topic.topic_id=points.topic_id
WHERE topic.creator='$user' GROUP by timestamp
HAVING certain time interval"
);
while ($row=mysql_fetch_assoc($query)){
$timestamp=$row['timestamp'];
$votes=$row['total'];
echo "[$timestamp,$vote],";
}
echo "];";
It would certainly be a lot saner to just use -1 as a downvote. Then you can simply run SUM(points_id)
To generate javascript-friendly notation, you can use good old mate json_encode.
$sql = "SELECT `timestamp`, SUM(points_id) FROM ..."; // yadda yadda
$result = mysql_query($sql);
$out = array();
while ($row = mysql_fetch_assoc($result)) {
$out[] = array((int) $row['timestamp'], (int) $row['total']);
}
echo "d = " . json_encode($out) . ";\n";

Categories