Run a second MySQL query based on results in PHP - php

EDIT: I've just thought I could run this as one query with something like this:
SELECT * FROM clubs
JOIN match_request_archive
ON (SELECT COUNT (clubs.id) AS requests FROM match_request_archive)
I appreciate though my syntax is horrendous I've just whipped this up and will tweak it now.
I have a basic script for displaying data in a table. I've got a problem I can't solve which is I need to run one simple query to show all the data to the user. But in the last column I need to run a separate query to get the result.
Basically the first column in my table has the unique ID of a Rugby Club on the database. In a separate table on the database is a list of all requests made by clubs to players. I want to display how many requests each club has made in the last column of my script below which means running this query:
SELECT * FROM match_request_archive WHERE club_id LIKE "$row['id']"
The $row['id'] is from the PHP script below:
<?php
include 'credentials.php';
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT * FROM clubs";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc())
{
echo "
<tr>
<td>" . $row['id'] . "</td>
<td>" . $row['club_name'] . "</td>
<td>" . $row['club_captain'] . "</td>
<td>" . $row['club_captain_number'] . "</td>
<td>" . $row['club_captain_email'] . "</td>
<td>TBC</td>
</tr>
";
}
} else {
echo "<tr><td>0 results</td></tr>";
}
$conn->close();
?>
To solve this I tried embedding a second script in the echo command but it's my understanding you can't do this and in any case it did cause a fatal error. I can run this query separately and have it displayed in a different table, my problem is I need this to be all in one table. I hope that all makes sense.

Executing query in loop is bad practice because it has very slow performance.
So you should try get all data by one query if it possible:
SELECT *, COUNT(*) FROM clubs
LEFT JOIN match_request_archive
ON match_request_archive.club_id = clubs.id
GROUP BY clubs.id

Related

save database data in a php array and process the data

I have more than one devices sending data to the database at the same time. even though I have a primary id for database, as there are more than one devices, selection of a particular value with primary id seems really hard. I have the unique names of each device (A, B, C etc.)
i am diplaying data in a php table. the table will have headings like |Serial number| voltage| current| Select|. here serial number has no any relationship with database. I use it to organize data in the php table. When user select a value say serial number 3, previous 5 values should be considered for avg calculation, here values with serial 3,4,5,6 and 7. my doubt is how to choose these particular serial values?. I was thinking of saving these table in a php array and use these serials as key values. Any suggestions?
<?php
$conn= mysqli_connect( $dbhost, $dbuser, $dbpass, $db );
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT Date, Voltage, Current FROM DataTable WHERE ID='A' ORDER BY Date DESC";
$result = $conn->query($sql);
//$i is used to assign serial number for each row
$i=1;
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo "<form action = 'samepage.php' method =get>";
echo "<tr>
<td>" . $i. "</td>
<td>" . $row["Time"]. "</td>
<td>" . $row["Voltage"] . "</td>
<td>" . $row["Current"]. "</td>
<td>"." <input type=hidden name=serialSelected value =" . $i."</td>
<td>"." <input type=submit name=Submit value=select >"." </td>
</tr>";
$i++;
echo "</form>";
}
echo "</table>";
} else { echo "0 results"; }
$avgCurrent=0;
$avgVoltage=0;
if(isset ($_GET['serialSelected'])){
//how to choose the value selected and the previous 4 values (total 5 values for avg calculation)
}

How to display grouped data in separate tables with a PHP loop?

I am new to phpmysqli. Here is what I have and what am trying to achieve: I will update this based on the recommendations;
Database sample data
I want to display the data on one page with separate tables for each student based on their sid. This is what I have tried so far;
<?php
include_once 'dbcon.php';
$results = $MySQLiconn->query('SELECT * FROM activitybook');
$students = [];
foreach ( $results->fetch_array() as $activity ) {
$students[$activity['sid']][] = $activity;
}
foreach($students as $sid=>$activities) {
foreach($activities as $activity) {
echo
"<table><tr>
<th>SID</th>
<th>Date</th>
<th>FName</th>
<th>LName</th>
<th>activity</th>
<th>time</th>
<th>score</th>
</tr>
<tr>
<td>" . $sid . "</td>
<td>" . $activity['fname'] . "</td>
<td>" . $activity['lname'] . "</td>
<td>" . $activity['activity'] . "</td>
<td>" . $activity['atime'] . "</td>
<td>" . $activity['ascore'] . "</td>
</tr></table>";
}
}
?>
This is what I get
What am trying to achieve is separate tables for each sid.
This is the sample of what I want to archive
You will need to "group" your result set data based on the sid value. As you iterate, check if you are changing groups or not.
I've added some refinements as well.
Name the columns in your SELECT clause so that you only retrieve exactly what you need.
Fetch an associative array, not a combination of indexed and associative elements.
Assign a temporary variable to help you determine if you are continuing a sid group or starting a new one (or if it is the first iteration, don't write </table>.
implode() helps to remove a lot of the code bloat.
Code:
$res = $conn->query("SELECT sid, fname, lname, activity, atime, ascore FROM activitybook ORDER BY sid");
$tmp = null;
$colheads = ['SID', 'FName', 'LName', 'activity', 'time', 'score'];
while ($row = $res->fetch_assoc()) { // don't produce more elements per row than needed
if ($tmp != $row['sid']) { // determine if a new group / sid value
if ($tmp !== null) {
echo '</table><br>'; // close the previous table
}
echo '<table border=1><tr><th>' , implode('</th><th>', $colheads) , '</th></tr>'; // start a new table & add headings
}
echo '<tr><td>' , implode('</td><td>', $row) , '</td></tr>'; // display the row data
$tmp = $row['sid']; // DUH, I FORGOT TO UPDATE $tmp!
}
if ($tmp !== null) {
echo '</table>'; // close the final table -- so long as there was at least one row in the result set
}
Requirements: Process a stream of ordered student records. The stream consists of Groups of Student Records. Each group is identified by at 'sid' column.
Each StudentGroup is wrapped in an HTML table
Each StudentRecord is one row of the table
What I like to do is structure the code according to the data. The data is structured as follows:
An Iteration of StudentRecordGroup
Each StudentRecordGroup consists of a Sequence of:
Process Start of Group
Iterate through the records belonging to the group
Process the end of the group
Notice there is no conditional statement anywhere in this process!
Now, how do we structure the code to do this. You cannot use a foreach loop! That only does the read at the end of the loop.
We have two loops:
The outer loop that processes All the groups of records.
The inner loop that process One complete group.
The technique to do this is called 'read ahead'. And is just what it says. You read the first record before starting the outer loop.
Source:
Working Code at Pastebin.com
Output:
SID Date FName LName activity time score
2 John Ppap 12 56 56
2 John Ppap 23 23 23
SID Date FName LName activity time score
3 Mito Mmito 34 12 12
3 Mito Mmito 45 45 45
SID Date FName LName activity time score
4 Uba Uuba 56 78 100
The code:
<?php // 53020396/how-to-display-grouped-data-in-separate-tables-with-a-php-loop
/* ---------------------------------------------------------------------------
* The input stream consists of an Ordered Iteration of:
* A collection of Individual Records for each Student (StudentRecordGoup)
*
* Each StudentRecordGoup consists of a Sequence of:
* Start of Group
* Iteration of Student records belonging to the group
* End of Group
*
* Notice: There is no 'IF' statement anywhere in the control logic for a group!
*
* Please note: There is exactly one place in the code to assign any appropriate action!
* i.e. The structure of the code exactly matched the structure of the data. :)
*
* This makes it easier to debug, maintain and amend?
*
* To do this we need 'state' information. Specifically that a record is part
* of the current 'student record group' group or not. How do we do this?
*
* We always need a record to test! Including at the start! We never read a record
* and then decide what to do with it. We always know where we are in the data
* structure and either the current record belongs to the group or not.
*
* We need to use a technique called 'Read Ahead'. Literally, There is always
* a record to process. You don't have to test it to know where you are.
* Once you process it then you immediately read the next record from the input.
* i.e. You end up reading a new record NOT JUST AT THE WND OF THE LOOP!
* You cannot use 'foreach' loops.
*
* We have to include Initialisation to setup code and any termination code.
*
* I will put all the 'action place holders' in functions. That way it avoids
* obscuring the high-level logic.
*/
// Get the ordered student detail records
$pdo = getPdoConnection();
$pdoResultSet = prepareAndExecuteQuery($pdo);
// Process all the students Record Groups - 'read ahead' of the row
$curStudentRecord = $pdoResultSet->fetch(); // is assoc array
while ($curStudentRecord !== false) { // process the student record groups
// process one complete student group...
$curStudentRecordGroupId = $curStudentRecord['sid'];
startStudendRecordGroup($curStudentRecordGroupId);
while ( $curStudentRecord !== false // check record belongs to the current group
&& $curStudentRecord['sid'] === $curStudentRecordGroupId) {
processStudentRecord($curStudentRecord);
$curStudentRecord = $pdoResultSet->fetch(); // read the next record
}
endStudendRecordGroup($curStudentRecordGroupId); // ignore the current record
// that is the next group!
}
// all groups have been processed
exit;
/* --------------------------------------------------------------------------
* Student record group processing
*/
function startStudendRecordGroup($curStudentRecordGroupId)
{
echo "<!-- new group: sid = $curStudentRecordGroupId -->";
echo "<table><tr><th>SID</th><th>Date</th><th>FName</th><th>LName</th>
<th>activity</th><th>time</th><th>score</th></tr>";
}
function processStudentRecord($curStudentRecord)
{
echo "<!-- group record: sid = {$curStudentRecord['sid']} -->";
echo "<tr>
<td>" . $curStudentRecord['sid'] . "</td>
<td>" . $curStudentRecord['fname'] . "</td>
<td>" . $curStudentRecord['lname'] . "</td>
<td>" . $curStudentRecord['col3'] . "</td>
<td>" . $curStudentRecord['col4'] . "</td>
<td>" . $curStudentRecord['col5'] . "</td>
</tr>";
}
function endStudendRecordGroup($curStudentRecordGroupId)
{
echo "<!-- end group: sid = $curStudentRecordGroupId -->";
echo "</table>";
}
/* --------------------------------------------------------------------------
* Database access
*/
// Execute query and return 'resultset'
function prepareAndExecuteQuery(\PDO $pdo)
{
$sql = 'SELECT id, sid, fname, lname, col3, col4, col5
FROM activity
ORDER BY sid, id';
$stmt = $pdo->prepare($sql);
$allOk = $stmt->execute();
return $stmt;
}
// DB Connection
function getPdoConnection()
{
$opt = array(
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_EMULATE_PREPARES => false,
);
$pdo = new \PDO('mysql:host=localhost;dbname=notmydb;', 'notme', 'notme', $opt);
return $pdo;
}
You can create a separate array of student ids and each time in loop check if that id exists in array than don't create a new table else create a new table. Use like this:
<?php
$res = $conn->query("SELECT * FROM activitybook");
$sId = [];
echo "<table>";
while($row=$res->fetch_array())
{
if (count($sId) == 0) {
$sId[] = $row['sid'];
}
if (!in_array($row['sid'], $sId)) {
$sId[] = $row['sid'];
echo "</table><table>";
}
echo
"<tr>
<th>SID</th>
<th>Date</th>
<th>FName</th>
<th>LName</th>
<th>activity</th>
<th>time</th>
<th>score</th>
</tr>
<tr>
<td>" . $row['sid'] . "</td>
<td>" . $row['fname'] . "</td>
<td>" . $row['lname'] . "</td>
<td>" . $row['activity'] . "</td>
<td>" . $row['atime'] . "</td>
<td>" . $row['ascore'] . "</td>
</tr>";
}
?>
Group your results by SID then loop on it:
$results = $conn->query('SELECT * FROM activitybook');
$students = []
foreach ( $results->fetch_array() as $activity ) {
$students[$activity['sid']][] = $activity;
}
foreach($students as $sid=>$activities) {
foreach($activities as $activity) {
echo
"<table><tr>
<th>SID</th>
<th>Date</th>
<th>FName</th>
<th>LName</th>
<th>activity</th>
<th>time</th>
<th>score</th>
</tr>
<tr>
<td>" . $sid . "</td>
<td>" . $activity['fname'] . "</td>
<td>" . $activity['lname'] . "</td>
<td>" . $activity['activity'] . "</td>
<td>" . $activity['atime'] . "</td>
<td>" . $activity['ascore'] . "</td>
</tr></table>";
}
}
Some tips for you:
Use variables with meaning names. What's inside your $row? Activities right? So name it $activity instead. And avoid abbreviations like $res.
The same is valid for your database columns. aid is not a good practice. Use just id for the primary key. Also sid should become student_id so people that reads your code understand that its a foreign key for the students table.

sql works on phpmyadmin but not on php script

I have 2 table names courses and institution.
Here is my query:
CREATE TEMPORARY TABLE
IF NOT EXISTS temp AS (SELECT course_name, ins_name
FROM courses
where course_name='ACCA') ;
select institution.ins_name, address, contact, website,
email from institution join temp on institution.ins_name = temp.ins_name
And here is my php script:
<?php
session_start();
include('db_connect.php');
$sql="CREATE TEMPORARY TABLE
IF NOT EXISTS temp AS (SELECT course_name, ins_name
FROM courses
where course_name='ACCA') ;
select institution.ins_name, address, contact, website, email from institution join temp on institution.ins_name = temp.ins_name";
$result= mysqli_query($conn, $sql) or die("MySQL error: " . mysqli_error($conn));
while ($row = mysqli_fetch_array($result)){
echo "<tr>";
echo "<td>" . $row['ins_name'] . "</td>";
echo "<td>" . $row['address'] . "</td>";
echo "<td>" . $row['contact'] . "</td>";
echo "<td>" . $row['website'] . "</td>";
echo "<td>" . $row['email'] . "</td>";
echo "</tr>";
}
echo "</table>"
?>
I can't figure out what the problem is. The error i get is:
MySQL error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select institution.ins_name, address, contact, website, email from institution j' at line 6
What am i doing wrong?
From Multiple Statements:
MySQL optionally allows having multiple statements in one statement
string. Sending multiple statements at once reduces client-server
round trips but requires special handling.
Multiple statements or multi queries must be executed with
mysqli_multi_query(). The individual statements of the statement
string are separated by semicolon. Then, all result sets returned by
the executed statements must be fetched.
Alternatively, just fire two queries.
Every query must be executed separately. create and select are two different queries so first you need to call mysqli_query for create and then mysqli_query for select
You need alias on each column :
select institution.ins_name, institution.address, institution.contact, institution.website, institution.email from institution join temp on institution.ins_name = temp.ins_name";

Page hangs on multi command mysqli php

So I'm pretty new to PHP and I'm mostly just struggling my way through it but I've hit a roadblock that I just can't get over.
My goal is to run a few commands to clear and update a standings table and then display the data in a table. I've got the table to display pretty much no problem but when I add the code in to update the table the page stops before it even displays the table and it's just a blank page, it wont even run any of the HTML.
Here's the PHP, I can provide the rest of the page code if needed.
http://pastebin.com/GZ3KcNXK
<?php
$con = mysqli_connect("localhost","uakronhv_admin","uakhvzdbadmin01","uakronhv_game1");
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$sql = "DELETE FROM standings WHERE 1=1; ";
$sql. = "INSERT INTO standings (`pId`,`pName`,`pStarve`) SELECT p.pId, concat(p.pFirst," ",p.pLast), TIMEDIFF(NOW(),s.lastTag) FROM players p left join starve s on p.pId = s.zId; ";
$sql.= $mysqli_real_escape_string("UPDATE standings SET sStatus = "Human" WHERE sId NOT IN (SELECT DISTINCT taggedId FROM tags); "):
$sql.= $mysqli_real_escape_string("UPDATE standings SET sStatus = "Zombie" WHERE (sId IN (SELECT DISTINCT taggedId FROM tags)) OR (sId IN (SELECT DISTINCT taggerId FROM tags)); "):
$que=$mysqli_query($sql);
$sp = mysqli_query($con,"call updateStandings()");
$result = mysqli_query($con,"SELECT * FROM standings");
echo "<table>
<tr>
<th>Id</th>
<th>Name</th>
<th>Status</th>
<th>Since Last Tag</th>
</tr>";
while($row = mysqli_fetch_array($result)) {
echo "<tr>";
echo "<td style=\"text-align:center\">" . $row['pId'] . "</td>";
echo "<td>" . $row['pName'] . "</td>";
echo "<td style=\"text-align:center\">" . $row['pStatus'] . "</td>";
if ($row['pStarve'] > '72:00:00')
echo "<td style=\"text-align:center\">Starved</td>";
else if
(is_null($row['pStarve']))
echo "<td style=\"text-align:center\">--</td>";
else
echo "<td >" . $row['pStarve'] . "</td>";
echo "</tr>";
}
echo "</table>";
mysqli_close($con);
?>
I'm just going to point out where the faults are, which may very well fix your code. If it doesn't, then you will need to read up on the better tutorials.
Regarding this code block:
$sql. = "INSERT INTO standings (`pId`,`pName`,`pStarve`) SELECT p.pId, concat(p.pFirst," ",p.pLast), TIMEDIFF(NOW(),s.lastTag) FROM players p left join starve s on p.pId = s.zId; ";
$sql.= $mysqli_real_escape_string("UPDATE standings SET sStatus = "Human" WHERE sId NOT IN (SELECT DISTINCT taggedId FROM tags); "):
$sql.= $mysqli_real_escape_string("UPDATE standings SET sStatus = "Zombie" WHERE (sId IN (SELECT DISTINCT taggedId FROM tags)) OR (sId IN (SELECT DISTINCT taggerId FROM tags)); "):
$que=$mysqli_query($sql);
The concatenation is incorrect $sql. = those should read as $sql .= which is why you say that the DELETE part works but not the rest following that statement. Had you used or die(mysqli_error($con)) to mysqli_query() it would have signaled the error.
Then you're probably wanting to sanitize input using mysqli_real_escape_string() but that's not how that function works and you don't use a $ sign in front of that function.
It works like this:
$variable = mysqli_real_escape_string($con, $_POST['variable']);
Read up on the function:
http://php.net/manual/en/mysqli.real-escape-string.php
Then you're using $mysqli_query with a dollar sign in front of that function, it's just mysqli_query.
Then you're doing SET sStatus = "Human" that should be single quotes and not double quotes SET sStatus = 'Human' and do the same for the other one.
Having used error reporting and checking for DB error using/adding or die(mysqli_error($con)) to mysqli_query() would have signaled the errors.
Error reporting should have given you warnings such as Undefined variable... in regards to $mysqli_query and $mysqli_real_escape_string.
That should give you enough information to debug your code.
Blank page often means syntax error. Maybe it's the one in front of the INSERT statement?
$sql. = "INSERT INTO standings ...";
Try this one ;)
$sql .= "INSERT INTO standings ...";
Edit: And as mentioned in the comments, it's the first step in debugging. Forgot to say it directly.

Way to utilise 2 tables within a single query

I had an assessment on pulling data from a table but i had to use two tables to do a calculation, i figured out a way to do it but it doesn't look good neither it would be good to keep using this way
$query = mysqli_query($connection, "SELECT * FROM metal");
$query2 = mysqli_query($connection, "SELECT * FROM conversion WHERE type = 'EUR'");
$data2 = mysqli_fetch_array($query2);
$query3 = mysqli_query($connection, "SELECT * FROM conversion WHERE type = 'USD'");
$data3 = mysqli_fetch_array($query3);
while($data = mysqli_fetch_array($query)){
echo "<tr>" . "<td>" . $data['metal'] . "</td>" . "<td>" . $data['cost'] . "</td>" . "<td>" . ($data['cost'] * $data3['amount']) . "</td>" . "</tr>";
}
This grabs cost on metal type then using another table calculates cost in Euro and USD, I don't want to use 3 querys and fetch them 3 times as it isn't computationaly effective is there a better way to do it
You'd need at least two, since you're fetching from two essentially unrelated tables
SELECT * FROM metal
SELECT * FROM conversion WHERE type IN ('EUR', 'USD')
the second query will fetch BOTH records, and then you'll just need some extra code to sort out which record is which.
Could you please post your overall table structure? In case you have a relation between these two table you could just join it.

Categories