I'm trying to come up with an efficient way of displaying some data but not succeeding at all.
The table is built dynamically from a few tables to show a row of headers with the columns populated showing the results by site e.g:
Site name | Column A | Column B | Column C => column headers continue from DB query
Site A | Result A | Result B | Result C
Site B | Result C | Result B | Result C
Site C | Result C | Result B | Result C
Results keep going vertically.
Here's the query I'm using
$risk_section=$row_risk_category['risksectid'];
mysql_select_db($database_auditing, $auditing);
$qry_selfsites = sprintf("SELECT
tblself.siteid AS selfsite,
tblsite.sitename AS sitename,
tblsite.address AS address,
tblpct.pctname AS pctname,
tblresultsnew.total,
tblresultsnew.auditid AS auditid,
tblriskcategories.risksectid AS risksectid,
tblriskcategories.risksection AS risksection
FROM tblself
LEFT JOIN tblresultsnew ON tblself.auditid = tblresultsnew.auditid
LEFT JOIN tblsite ON tblself.siteid = tblsite.siteid
LEFT JOIN tblpct ON tblsite.pctid = tblpct.pctid
LEFT JOIN tblriskcategories ON
tblresultsnew.risksectid=tblriskcategories.risksectid
WHERE tblsite.pctid IN (SELECT pctid FROM tblreportpcts WHERE
pctreportid='$pctreportid')
AND tblsite.sitetypeid IN (SELECT sitetypeid FROM tblreportsites WHERE
pctreportid='$pctreportid')
AND tblself.year = %s
ORDER BY tblsite.pctid,tblsite.sitename",
GetSQLValueString($yearofrpt, "int"));
$selfsites = mysql_query($qry_selfsites, $auditing) or die(mysql_error());
$totalRows_selfsites = mysql_num_rows($selfsites);
So the question is, is there a way to get the data from the above query (or an adapted version thereof) to build the table dynamically with all the results lining up correctly?
So far, I can only get it to build vertically.
Sorry, edit time (having worked with the answer below, I realised I hadn't got the question worded very well)
What I'm trying to get is a row of column headers from the query (tblriskcategories.risksection AS risksection) These populate horizontally to give the columns names.
Then underneath, the sitename is displayed with the result corresponding to the column header above i.e.
<table>
<tr>
<th>Sitename</th>
<?php while($row_selfsites=mysql_fetch_assoc($selfsites){
//loop through the section headers pulled from the DB (tblriskcategories)
<th><?php echo $row_selfsites['risksection'];//show the section headers?></th>
<?php }
//end header loop then start another loop to show a row for each site pulled
//out by the query and show the relevant results in the correct column
while($row_selfsites=mysql_fetch_assoc($selfsites)) {
//do the vertical drop matching the header rows with the sitenames from tblsite
//and the results from tblresultsnew
?>
<tr>
<td><?php echo $row_selfsites['sitename'];?></td>
<td><?php echo $row_selfsites['total'];
//these need to grow to fit the headers and each site?></td>
<tr>
<?php } //end displayed data loop?>
</table>
The relevant tables structure below:
tblresultsnew resultsid,auditid,risksectid,total
tblriskcategories risksectid, risksection
tblself selfauditid,siteid,auditid
tblsite siteid,sitename
So tblself holds the list of sites we need the data for and the relevant auditid,
tblresultsnew holds the results - the total column - for each risksectid and each auditid eg, one auditid can have approx 8 risksectid's each with corresponding total
tblriskcategories holds the column headings
tblsite holds the site data to make it mean something
I hope this explains the question a little further.
Thanks again for all the help.
Dave
$rows = array(
0 => array('headingA' => 'results1a', 'headingB' => 'results1b', ),
1 => array('headingA' => 'results2a', 'headingB' => 'results2b', ),
2 => array('headingA' => 'results3a', 'headingB' => 'results3b', ),
);
// $rows is spoofing a db result set as an array
//var_dump( $rows );
$first = true ;
$header_row = "START TABLE <br />" ;
$data_rows = "";
foreach( $rows as $row ) {
foreach( $row as $key=>$value ){
if( $first === true ){
$header_row .= "$key | ";
}
$data_rows .= "$value |";
}
if( $first ) $header_row .="<br />";
$data_rows .= "<br />";
$first = false;
}
echo $header_row . $data_rows . "END TABLE";
Gives:
START TABLE
headingA | headingB |
results1a |results1b |
results2a |results2b |
results3a |results3b |
END TABLE
Is that the kind of solution you are after?
Related
First off all I am slightly confused what the best implemtentation would be for the following problem i.e pure can it be done with only mysql without altering tables or would I need a combination of PHP and mysql as I am currently doing.
Please keep that in mind as you read on:
Question Info
A Pickem game works as follow:
1- Display all matches / fixtures in a round for a tournament.
2- User enters which teams he thinks will win each fixture.
The fixtures are pulled from a table schedule and the users results are recorded in a table picks
Keep In mind
Each round can have a number of matches (anywhere between 1 to 30+ matches)
What I am trying todo / PROBLEM
I am trying to calculate how many users selected team1 to win and how many users selected team2 to win for a given round in a tournament.
Example
Manchester United: 7 users picked |
Arsenal 3: users picked
MYSQL TABLES
schedule table Schedule of upcoming games
picks table User Picks are recorded in this table
Expected Output From Above Tables After Calculations
So for Super Rugby Round 1 it should read as follow:
gameID 1 4 picks recorded, 2 users selected Jaquares 1 user Selected Stormers (ignore draw fro now)
gameID 2 4 picks recorded, 4 users selected Sharks, 0 users selected Lions
My Code
function calcStats($tournament, $week)
{
global $db;
//GET ALL GAMES IN TOURNAMENT ROUND
$sql = 'SELECT * FROMpicks
WHERE picks.tournament = :tournament AND picks.weekNum = :weekNum ORDER BY gameID';
$stmnt = $db->prepare($sql);
$stmnt->bindValue(':tournament', $tournament);
$stmnt->bindValue(':weekNum', $week);
$stmnt->execute();
if ($stmnt->rowCount() > 0) {
$picks = $stmnt->fetchAll();
return $picks;
}
return false;
}
test.php
$picks = calcStats('Super Rugby', '1');
foreach($picks as $index=> $pick) {
if($pick['gameID'] !== $newGameID){
?>
<h1><?php echo $pick['gameID']?></h1>
<?php
//reset counter on new match
$team1 = 0;
$team2 = 0;
}
if($pick['picked'] === $newPick){
//gameID is passed as arrayKey to map array index to game ID
//team name
$team1[$pick['picked']];
//number times selected
$team1Selections[$pick['gameID']] = $team1++;
}
else if($pick['picked'] !== $newPick){
///gameID is passed as arrayKey to map array index to game ID
//team name
$team2[$pick['picked']];
$team2Selections[$pick['gameID']] = $team2++;
}
$newPick = $pick['picked'];
$newGameID = $pick['gameID'];
}
PRINT_R() Of function $picks = calcStats('Super Rugby', '1')
I hoe my question makes sense, if you need any additional information please comment below, thank you for taking the time to read.
It seems that you're doing too much within PHP that can be easily done within MySQL; consider the following query:
SELECT gameID, team, COUNT(*) AS number_of_picks
FROM picks
WHERE picks.tournament = :tournament AND picks.weekNum = :weekNum
GROUP BY gameID, team
ORDER BY gameID, team
This will give the following results, given your example:
1 | Jaquares | 2
1 | Stormers | 1
1 | Draw | 1
2 | Sharks | 4
Then, within PHP, you perform grouping on the game:
$result = array();
foreach ($stmnt->fetchAll() as $row) {
$result[$row['gameID']][] = $row;
}
return $result;
Your array will then contain something like:
[
'1' => [
[
'gameID' => 1,
'team' => 'Jaquares',
'number_of_picks' => 2,
],
'gameID' => 1,
'team' => 'Stormers',
'number_of_picks' => 1,
],
...
I am a newbie to PHP and I am stuck at a certain point. I tried looking up a solution for it however, I didn't find exactly what I need.
My goal is to create a leaderboard, in which the values are displayed in descending order plus the rank and score are displayed. Furthermore, it should also display whether or not a tie is present.
The database should look like this:
+---------+------+----------------+-------+------+
| user_id | name | email | score | tied |
+---------+------+----------------+-------+------+
| 1 | SB | sb#gmail.com | 1 | 0 |
+---------+------+----------------+-------+------+
| 2 | AS | as#web.de | 2 | 0 |
+---------+------+----------------+-------+------+
| 3 | BR | br#yahoo.com | 5 | 1 |
+---------+------+----------------+-------+------+
| 4 | PJ | pj#gmail.com | 5 | 1 |
+---------+------+----------------+-------+------+
And the outputted table should look something like this:
+------+-------------+-------+------+
| rank | participant | score | tied |
+------+-------------+-------+------+
| 1 | BR | 5 | Yes |
+------+-------------+-------+------+
| 2 | PJ | 5 | Yes |
+------+-------------+-------+------+
| 3 | AS | 2 | No |
+------+-------------+-------+------+
| 4 | SB | 1 | No |
+------+-------------+-------+------+
I managed to display the rank, participant and the score in the right order. However, I can't bring the tied column to work in the way I want it to. It should change the value, whenever two rows (don't) have the same value.
The table is constructed by creating the <table> and the <thead> in usual html but the <tbody> is created by requiring a php file that creates the table content dynamically.
As one can see in the createTable code I tried to solve this problem by comparing the current row to the previous one. However, this approach only ended in me getting a syntax error. My thought on that would be that I cannot use a php variable in a SQL Query, moreover my knowledge doesn't exceed far enough to fix the problem myself. I didn't find a solution for that by researching as well.
My other concern with that approach would be that it doesn't check all values against all values. It only checks one to the previous one, so it doesn't compare the first one with the third one for example.
My question would be how I could accomplish the task with my approach or, if my approach was completely wrong, how I could come to a solution on another route.
index.php
<table class="table table-hover" id="test">
<thead>
<tr>
<th>Rank</th>
<th>Participant</th>
<th>Score</th>
<th>Tied</th>
</tr>
</thead>
<tbody>
<?php
require("./php/createTable.php");
?>
</tbody>
</table>
createTable.php
<?php
// Connection
$conn = new mysqli('localhost', 'root', '', 'ax');
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// SQL Query
$sql = "SELECT * FROM names ORDER BY score DESC";
$result = $conn->query("$sql");
// Initalizing of variables
$count = 1;
$previous = '';
while($row = mysqli_fetch_array($result)) {
$current = $row['score'];
$index = $result['user_id']
if ($current == $previous) {
$update = "UPDATE names SET tied=0 WHERE user_id=$index";
$conn->query($update);
}
$previous = $current;
?>
<tr>
<td>
<?php
echo $count;
$count++;
?>
</td>
<td><?php echo $row['name'];?></td>
<td><?php echo $row['score'];?></td>
<td>
<?php
if ($row['tied'] == 0) {
echo 'No';
} else{
echo 'Yes';
}
?>
</td>
</tr>
<?php
}
?>
I think the problem is here
$index = $result['user_id'];
it should be
$index = $row['user_id'];
after updating tied you should retrieve it again from database
So I solved my question by myself, by coming up with a different approach.
First of all I deleted this part:
$current = $row['score'];
$index = $result['user_id']
if ($current == $previous) {
$update = "UPDATE names SET tied=0 WHERE user_id=$index";
$conn->query($update);
}
$previous = $current;
and the previous variable.
My new approach saves the whole table in a new array, gets the duplicate values with the array_count_values() method, proceeds to get the keys with the array_keys() method and updates the database via a SQL Query.
This is the code for the changed part:
// SQL Query
$sql = "SELECT * FROM names ORDER BY score DESC";
$result = $conn->query("$sql");
$query = "SELECT * FROM names ORDER BY score DESC";
$sol = $conn->query("$query");
// initalizing of variables
$count = 1;
$data = array();
// inputs table into an array
while($rows = mysqli_fetch_array($sol)) {
$data[$rows['user_id']] = $rows['score'];
}
// -- Tied Column Sort --
// counts duplicates
$cnt_array = array_count_values($data);
// sets true (1) or false (0) in helper-array ($dup)
$dup = array();
foreach($cnt_array as $key=>$val){
if($val == 1){
$dup[$key] = 0;
}
else{
$dup[$key] = 1;
}
}
// gets keys of duplicates (array_keys()) and updates database accordingly ($update query)
foreach($dup as $key => $val){
if ($val == 1) {
$temp = array_keys($data, $key);
foreach($temp as $k => $v){
$update = "UPDATE names SET tied=1 WHERE user_id=$v";
$conn->query($update);
}
} else{
$temp = array_keys($data, $k);
foreach($temp as $k => $v){
$update = "UPDATE names SET tied=0 WHERE user_id=$v";
$conn->query($update);
}
}
}
Thank you all for answering and helping me get to the solution.
instead of the update code you've got use something simular
$query = "select score, count(*) as c from names group by score having c > 1";
then you will have the scores which have a tie, update the records with these scores and your done. Make sure to set tie to 0 at first for all rows and then run this solution
UPDATE for an even faster solution sql based:
First reset the database:
$update = "UPDATE names SET tied=0";
$conn->query($update);
All records have a tied = 0 value now. Next update all the records which have a tie
$update = "update docs set tied = 1 where score IN (
select score from docs
group by score having count(*) > 1)";
$conn->query($update);
All records with a tie now have tied = 1 as we select all scores which have two or more records and update all the records with those scores.
I am displaying the complete record of the user in the My profile section, I am fetching all the rows , but the problem is within the rows I've got two fields as arrays, which are 'secondarySubject' and 'secondaryGrade' now I want the display to be something like this
2002-2004 ----------- A Level ------- School Name
Science A
Maths B
I am able to display them but it prints the dates, school name and level name with every subject rather than just once for all the subjects. I am posting my code, can someone pleaseeee help me with it.
$result2 = $db->query('
SELECT *
FROM secondaryEducation
WHERE userID = "'.$graduateID.'"
ORDER BY secondaryFinishDate DESC
');
$totalRows2 = mysql_num_rows($result2);
if($totalRows2 > 0)
{
$html .= '<h2>Secondary Education: '.$option.'</h2>';
while($row = mysql_fetch_assoc($result2))
{
$startYear = formatDate($row['secondaryStartDate'], 'Y');
$finishYear = formatDate($row['secondaryFinishDate'], 'Y');
if (!empty($row['secondaryGrade']))
$secondaryGrade = getSecondaryGradeName($row['secondaryGrade']);
else
$secondaryGrade = $row['secondaryGradeCustom'];
$html .= '
<div class="secondaryListing">
<div><strong>'.$startYear.' - '.$finishYear.' '.stripslashes($row['secondarySchool']).'</strong></div>
<div>'.stripslashes(getSecondaryLevelName($row['secondaryLevel'])).' in '.stripslashes(getSecondarySubjectName($row['secondarySubject'])).' - '.stripSlashes($secondaryGrade).'</div>
</div><!-- End education listing -->
';
}
}
It looks like those are inside the while statement. Every time it loops it will include it. Try moving it outside the while statement.
i need help displaying this in two different lists
$domains_sql = mysql_query("SELECT domains_id, domains_url, keywords_id, keywords_word, domains_comments_comment
FROM
(
SELECT domains_id,domains_url
FROM domains
ORDER BY RAND()
LIMIT 1
) as d
INNER JOIN domains_comments
ON domains_comments_domain = domains_id
INNER JOIN domains_keywords
ON domains_keywords_website = domains_id
INNER JOIN keywords
ON domains_keywords_keyword = keywords_id
ORDER BY keywords_word ASC") or die (mysql_error());
$num = mysql_num_rows($domains_sql);
$current_price = "";
for($i=0;$i<$num;$i++){
$domains_result = mysql_fetch_array($domains_sql);
$domains_id = $domains_result['domains_id'];
$domains_url = $domains_result['domains_url'];
$domains_name = preg_replace('#^https?://www.#', '', $domains_url);
$keywords_id = $domains_result['keywords_id'];
$keywords_word = $domains_result['keywords_word'];
$domains_comments = $domains_result['domains_comments_comment'];
if($domains_url != $current_price) {
echo $domains_name."<br /><br />";
$current_price = $domains_url;
}
echo $keywords_word."<br />";
echo $domains_comments."<br />";
}
prints out:
MS Office
domain 1
MS Office
domain 1 - part 1
MySQL
domain 1
MySQL
domain 1 - part 1
PHP
domain 1
PHP
domain 1 - part 1
Visual Basic
domain 1
Visual Basic
domain 1 - part
and i need it to be:
(info from keywords)
MS Office
MySQL
PHP
Visual Basic
(info from comments)
domain 1
domain 1 - part 1
I'm not sure if I see how your domain comments and keywords are related, and if you simply want two lists or if you want one comment-list per keyword.
Anyway, you could rewrite your query logic to make a primary query for the keywords, and then run simpler queries for the comments (either one for all, or one per keyword), but if your query time and dataset is such that you prefer doing it in a single query you can restructure the data in multiple-leve arrays.
Also, i presume you only want to list every item once.
$keywords = array();
$comments = array(); //if you want all comments in one list
for($i=0;$i<$num;$i++){
$domains_result = mysql_fetch_array($domains_sql);
//Stores complete row data, only keeps the last, if the same value is fetched from the db several times
$keywords [$domains_result['keywords_word']] = $domains_result;
$comments[$domains_result['domains_comments_comment']] = $domains_result;
}
//Now you have the two list, could be printed several ways, to only print the values
print implode("<br />\n",array_keys($keywords));
print "<br />";
print implode("<br />\n",array_keys($comments));
//Loop trough
foreach ($keywords as $keyword=>$data) {
print "$keyword<br>\n";
print $data['keywords_word']."<br>\n";
print_r($data);
}
I have a table which looks something like the following (first row is columns):
|section | col1 | col2 |
|----------------------|
|bananas | val | val2 |
|----------------------|
|peaches | val | val2 |
With some code to check if a section value matches up with one of the values in an array:
$sectionscope = Array('bananas', 'apples');
$sections = mysql_query("SELECT section FROM table WHERE col1=val AND col2=val2");
if (mysql_num_rows($sections)) {
$i = 0;
while ($row = mysql_fetch_array($sections)) {
if (in_array($row[$i], $sectionscope)) {
$section = $sectionscope[array_search($row[$i], $sectionscope)];
$section_is_valid = 1;
}
$i++;
}
}
If I echo the output from the while loop using echo $row[$i], it gives me: bananas
Doing the select from PHPmyadmin works fine
Can you tell me what I'm doing wrong here?
Thanks,
SystemError
Why are you incrementing $i in the while loop. Your query will return two rows and when you loop through the results, you can access the section value using $row[0] each time.
while ($row = mysql_fetch_array($sections)) {
echo $row[0];
}
This will print bananas and peaches.
In your code, when you enter the while loop second time, you are trying to retrieve section value using $row[1] (since your $i has incremented to 1), which will be null since your query result only contains one column.