I'm making a survey tracking website and I'm having trouble. I want to display all surveys that have been completed in the last 7 days. I'm using mysqli_fetch_row to see if any rows are retrieved, and if they are display them. If they aren't any compelted in the last 7 days, I want it to display the words "no recently compelted surveys to show."
<?php
require('db/connect.php');
if (!isset($_GET['sort'])) {
$sort = 'client_id';
} else {
$sort = $_GET['sort'];
}
if ($result = $db->query("SELECT client_id, date_added, client, email, date_sent, date_completed FROM clients NATURAL JOIN surveys WHERE date_completed BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE() ORDER BY $sort")) {//shows surveys completed in the last 7 days
if (mysqli_fetch_row($result) == 0) {
echo "No recently completed surveys to show.";
} else {
echo "<table>";
echo "<tr><th><a href='portal.php?sort=client_id'>ID</a></th><th><a href='portal.php?sort=date_added'>Date Added</a></th><th><a href='portal.php?sort=client'>Client</a></th><th><a href='portal.php?sort=email'>Email</a></th><th><a href='portal.php?sort=date_sent'>Sent</a></th><th><a href='portal.php?sort=date_completed'>Completed</a></th>";
$rows = $result->num_rows;
for ($num = 0; $num < $rows; ++$num) {
$row = $result->fetch_array(MYSQLI_NUM);
$client_id = $row[0];
$date = $row[1];
$client = $row[2];
$email = $row[3];
$sent = $row[4];
$completed = $row[5];
echo "<tr>";
echo "<td>$client_id</td>";
echo "<td>$date</td>";
echo "<td>$client</td>";
echo "<td>$email</td>";
echo "<td>$sent</td>";
echo "<td><a href='survey/completed/index.php?id=$client_id'>$completed</a></td>";
echo "</tr>";
}
echo "</table>";
}
}
?>
When I remove the if clause for mysqli_fetch_row, it displays ALL of the recently completed surveys, but if I leave it in, it ALWAYS leaves one out. Can anyone help?
You are discarding the first when you do the test. You can get the number of rows like this instead:
if ($result->num_rows == 0) {
echo "No recently completed surveys to show.";
} else {
// ....
}
Docs : mysqli_result::$num_rows
Related
just wondered if there was a a faster way of running this query? I have over 250K rows in my 'results' table. The code searches the table for all of the different types of race a trainer has run. It the looks at how many races that trainer has ran in the type of race. Then it looks at hoe many races he/she has won. Hope this is enough information. Thanks for looking.
echo "<div style='text-align:center;'>";
echo "<table id='main_table'>";
echo "<tr ><td align = center colspan = 4>".$trainer."</td></tr>";
$result = mysqli_query($db,"SELECT
DISTINCT RaceType AS racetype
FROM results
WHERE trainer = '$trainer' ORDER BY RaceType ASC"); //placing_numerical,
while($row = mysqli_fetch_array( $result ))
{
echo "<tr>";
echo "<td>";
echo $row['racetype'];
echo "</td>";
echo "<td>";
$result_horse = mysqli_query($db,"
SELECT
COUNT(id) AS result_run
FROM results
WHERE trainer = '$trainer' AND RaceType = '".$row['racetype']."'
");
$row_horse = mysqli_fetch_array( $result_horse );
echo $row_horse['result_run'];
$a = $row_horse['result_run'];
echo "</td>";
echo "<td>";
$result_horse1 = mysqli_query($db,"
SELECT
COUNT(id) AS result_win
FROM results
WHERE trainer = '$trainer' AND RaceType = '".$row['racetype']."' AND placing_numerical = '1'
");
$row_horse1 = mysqli_fetch_array( $result_horse1 );
echo $row_horse1['result_win'];
$b = $row_horse1['result_win'];
echo "</td>";
echo "<td>";
$percent = ($b / $a ) * 100;
$percent = sprintf('%0.0f', $percent);
echo $percent."%";
echo "</td>";
echo "</tr>";
}
echo "</table>";
Here are two suggestions you can check :-
For row_horse and row_horse1 , use "mysqli_fetch_assoc" instead of "mysqli_fetch_array" .
Try to write a single query taking all the three queries and it will save you more time what you are expecting .
I have “ordered by” a database to be in ascending country order, then descending years. Each database record contains: countryname, year, details. There are many duplicate countries, but the years are different. For instance:
Albania, 2000, details
Albania, 1965, details
Croatia, 2014, details
Croatia, 2003, details
Can’t figure out how to echo the array to get results like the following where country is on one line and years & details are listed below without duplicating the name of the country:
Albania
2000, details
1965, details
Croatia
2014, details
2003, details
Seems like I need foreach distinct country, echo year and details?
Here is my php so far:
$result = mysql_query("SELECT country, year, details FROM studies ORDER BY country, year DESC ");
//output data from each row in db
while($row = mysql_fetch_array($result)) {
echo " Country: " .$row['country']. "<br /> Year: " .$row['year']. " Details: ".$row['details']. "<br /><br /> ";
}
Would appreciate any help, I'm stumped!
Try adding a country check:
$newcountry = '';
while($row = mysql_fetch_array($result)) {
if ($newcountry != $row['country']) {
echo "Country:". $row['country']."<br />";
$newcountry = $row['country'];
}
echo " Year: " .$row['year']. " Details: ".$row['details']. "<br /><br /> ";
}
This should work, because you have ordered your query by Country. This is critical, otherwise you should absolutely add a GROUP BY clause to your SQL.
EDIT: to add a <div> around the group, you simply would change the echo sequence, checking first to see if the country has already been set once. It would look like:
$newcountry = 'undefined';
while($row = mysql_fetch_array($result)) {
if ($newcountry !='undefined' && $newcountry != $row['country']){
echo '</div>'; // only add a closing div if a new country (and not 1st)
}
if ($newcountry != $row['country']) {
echo "Country:". $row['country']."<br /><div class='countryDetail'>";
$newcountry = $row['country'];
}// added the start of the <div>
echo " Year: " .$row['year']. " Details: ".$row['details']. "<br /><br /> ";
}
if ($newcountry != 'undefined') { //make sure at least one <div> is set
echo "</div>"; // close the last <div>
}
I added the class countryDetail to the div, so you can use this with toggle in your jQuery.
You can use nested while loops. You might also want to use PDO/mysqli_ functions/prepared statements in place of mysql_ functions:
// get unique country list first
$sql1 = "SELECT DISTINCT(country) FROM studies ORDER BY country";
$result1 = mysql_query($sql1);
// iterate through result set of sql1
while($row1 = mysql_fetch_array($result1))
{
$country = $row1['country'];
echo "<br>"; // new line
echo $country;
// get year, details for each country
$sql2 = "SELECT year, details FROM studies WHERE country = '$country' ORDER BY year DESC";
$result2 = mysql_query($sql2);
// iterate through result set of $sql2
while ($row2 = mysql_fetch_array($result2))
{
echo "<br>"; // new line
echo $row2['year']. ", " . $row2['details'];
}
}
loop party!
$rows = [];
while($row = mysql_fetch_array($result)) {
$rows[ $row['country'] ] = [ $row['year'], $row['details'] ];
}
foreach($rows as $country => $row) {
$details = array_map(function($items) { return sprintf("\t - %s: %s\n", $items[0], $items[1]) }, $row);
echo sprintf("\n%s:\n %s", $country, $details);
}
My solution to this is at the bottom
My issue is: I am trying to display foreign key data, but because there is more than one foreign key, I am getting a 'duplicate' query for each of the foreign keys.
http://i.imgur.com/Gfqx497.png
As you can see, I can query the correct data, but I don't know how to attach the other foreign key data to the same 'one line output'.
I've been lurking stackoverflow for a while to find an answer to my problem and I'm at a wits end. I have found quite a number of threads, such as the two links below, where I believe people are asking the same thing, however I can't seem to wrap my head around getting the solution to work in my case. From my understanding, I need to be using aliases for the tables, however I've tried multiple different interpretations of the solutions and can't recreate the solution.
How do I merge two or more rows based on their foreign key
mysql query 2 foreign keys
--
I've got two tables ('Minions and Ability'), one of which has four foreign keys linking to the other.
http://i.imgur.com/ctpFHur.png
This is the php code that I'm using for the query, which is mostly taken from PHP and MySQL Web Development 4th Edition (Welling, Thomson) which I purchased to get me started with php and mysql.
$query = "SELECT minions.name, minions.summon, minions.attack,
minions.health, minions.race, minions.rarity,
minions.ability1, minions.ability2, minions.ability3,
minions.ability4, minions.imagebig,
ability.ability
AS ability FROM minions
INNER JOIN ability on
minions.ability1 = ability.abilityid
OR minions.ability2=ability.abilityid";
//Only trying for 2 foreign keys to try get it to work
$result = $db->query($query);
$num_results = $result->num_rows;
echo "<p>Number of items found: ".$num_results."</p>";
for ($i=0; $i <$num_results; $i++){
$row = $result->fetch_assoc();
//echo "<p><strong>".($i+1).". Name: ";
echo "<p><strong>";
echo htmlspecialchars(stripslashes($row['name']));
echo "</strong><br />Summoning cost: ";
echo stripslashes($row['summon']);
echo "<br />Attack: ";
echo stripslashes($row['attack']);
echo "<br />Health: ";
echo stripslashes($row['health']);
echo "<br />Race: ";
echo stripslashes($row['race']);
echo "<br />Rarity: ";
echo stripslashes($row['rarity']);
//if (stripslashes($row['ability'] != NULL)){
echo "<br />Abilty: ";
echo stripslashes($row['ability']);
//}
echo "<br />";
$imageMinion = stripslashes($row['imagebig']);
// $iwidth = 25;
// $iheight = 100;
// echo '<img src="img/'.$imageMinion.'.png" style="width:'.$iwidth.'px;height:'.$iheight.'px;">';
//echo "<br />";
echo '<img src="img/'.$imageMinion.'.png">';
echo "</p>";
Could someone please guide me to getting this to display correctly? I've tried to follow the other solutions and just can't seem to get the alias naming correct, if I'm correct in thinking that is the solution.
========EDIT REGARDING ANSWER FROM verbumSapienti===========
I am embarrassingly unable to get your Answer to work. This is how the code looks.
$query = "SELECT minions.name, minions.summon, minions.attack, minions.health,
minions.race, minions.rarity, minions.ability1, minions.ability2,
minions.ability3, minions.ability4, minions.imagebig,
ability.ability
AS ability
FROM minions
INNER JOIN ability
ON minions.ability1 = ability.abilityid
OR minions.ability2 = ability.abilityid
OR minions.ability3 = ability.abilityid
OR minions.ability4 = ability.abilityid";
$result = $db->query($query);
$num_results = $result->num_rows;
echo "<p>Number of items found: ".$num_results."</p>";
for ($i=0; $i <$num_results; $i++){
$row = $result->fetch_assoc();
$abilities = array('ability1', 'ability2', 'ability3', 'ability4');
foreach($abilities as $ability)
{
$q = "SELECT $ability FROM minions WHERE name={$row['name']}";
$result = $db->query($q);
$row2 = $result->fetch_assoc();
$abilitiesArr[] = $row2[$ability];
}
echo "<p><strong>";
echo htmlspecialchars(stripslashes($row['name']));
echo "</strong><br />Summoning cost: ";
echo stripslashes($row['summon']);
echo "<br />Attack: ";
echo stripslashes($row['attack']);
echo "<br />Health: ";
echo stripslashes($row['health']);
echo "<br />Race: ";
echo stripslashes($row['race']);
echo "<br />Rarity: ";
echo stripslashes($row['rarity']);
foreach($abilitiesArr as $ability)
{
$q = "SELECT $ability FROM ability";
$result = $db->query($q);
$row = $result->fetch_assoc();
echo "<br />Ability: $row";
}
/*if (stripslashes($row['ability'] != NULL)){
echo "<br />Abilty: ";
echo stripslashes($row['ability']);
}*/
echo "<br />";
$imageMinion = stripslashes($row['imagebig']);
echo '<img src="img/'.$imageMinion.'.png">';
echo "</p>";
}
I've tried changing around a few things and haven't had any success. As is, I get the following error:
Fatal error: Call to a member function fetch_assoc() on a non-object in D:\Xampp\htdocs\ocduels\results.php on line 87
Which is:
$row2 = $result->fetch_assoc();
In:
$abilities = array('ability1', 'ability2', 'ability3', 'ability4');
foreach($abilities as $ability)
{
$q = "SELECT $ability FROM minions WHERE name={$row['name']}";
$result = $db->query($q);
$row2 = $result->fetch_assoc();
$abilitiesArr[] = $row2[$ability];
}
::MY SOLUTION TO THIS::
This seems to work. I don't think its efficient, but its enough to allow me to continue learning. Thank you for all the responses. This allows me to find a 'Minion' and only have one instance of the 'Minion' when there is more than 1 Foreign Key with data.
$query = "SELECT
m.name as m_name,
m.summon as m_summon,
m.attack as m_attack,
m.health as m_health,
m.race as m_race,
m.rarity as m_rarity,
m.ability1 as m_ability1,
m.ability2 as m_ability2,
aa.ability as a_ability,
ab.ability as b_ability,
m.imagebig as m_imagebig
FROM minions m
LEFT JOIN ability aa
ON m.ability1 = aa.abilityid
LEFT JOIN ability ab
ON m.ability2 = ab.abilityid";
$result = $db->query($query);
$num_results = $result->num_rows;
echo "<p>Number of items found: ".$num_results."</p>";
for ($i=0; $i <$num_results; $i++){
$row = $result->fetch_assoc();
echo "<p><strong>";
echo htmlspecialchars(stripslashes($row['m_name']));
echo "</strong><br />Summoning cost: ";
echo stripslashes($row['m_summon']);
echo "<br />Attack: ";
echo stripslashes($row['m_attack']);
echo "<br />Health: ";
echo stripslashes($row['m_health']);
echo "<br />Race: ";
echo stripslashes($row['m_race']);
echo "<br />Rarity: ";
echo stripslashes($row['m_rarity']);
if (stripslashes($row['a_ability'] != NULL)){
echo "<br />Ability 1: ";
echo stripslashes($row['a_ability']);
}
if (stripslashes($row['b_ability'] != NULL)){
echo "<br />Ability 2: ";
echo stripslashes($row['b_ability']);
}
echo "<br />";
$imageMinion = stripslashes($row['m_imagebig']);
echo '<img src="img/'.$imageMinion.'.png">';
echo "</p>";
}
Try DISTINCT keyword to restrict duplicate values.
SELECT DISTINCT minions.name, minions.summon, minions.attack,
minions.health, minions.race, minions.rarity,
minions.ability1, minions.ability2, minions.ability3,
minions.ability4, minions.imagebig,
ability.ability
AS ability FROM minions
INNER JOIN ability on
minions.ability1 = ability.abilityid
OR minions.ability2=ability.abilityid";
you could try a subquery that prints only the ability text for each ability ID contained in each minion's attributes, maybe something along the lines of:
$abilities = array('ability1', 'ability2', 'ability3', 'ability4');
foreach($abilities as $ability)
{
$q = "SELECT $ability FROM minions WHERE name={$row['name']}";
$result = $db->query($q);
$row2 = $result->fetch_assoc()
$abilitiesArr[] = $row2[$ability];
}
then replace
echo "<br />Abilty: ";
echo stripslashes($row['ability']);
with
foreach($abilitiesArr as $ability)
{
$q = "SELECT $ability FROM ability";
$result = $db->query($q);
$row = $result->fetch_assoc()
echo "<br />Ability: $row";
}
When the number of results is one greater than the total loss is entered correctly, but one is subtracted from the list. For example: Found 12 results but only 11 are listed:
$goto = mysql_fetch_array($query);
$results = mysql_num_rows($query);
if($results == 1){
header('Location: movie.php?id='.$goto['id']);}
echo '<p><h2>Results for search "'.$_GET["search"].'": </h2></p>';
echo '<hr />';
echo "Found ".$total." result(s).</p><br>";
echo '<ol class="list">';
while ($resultado = mysql_fetch_assoc($query)) {
$titulo = $resultado['title'];
echo '<li>';
$link = 'http://localhost/lab/movie.php?id=' . $resultado['id'];
Thank you in advance for your help.
You need to do something like this:
$results = mysql_num_rows($query);
if($results == 1){
$goto = mysql_fetch_array($query);
header('Location: movie.php?id='.$goto['id']);}
}
echo '<p><h2>Results for search "'.$_GET["search"].'": </h2></p>';
echo '<hr />';
echo "Found ".$results." result(s).</p><br>";
echo '<ol class="list">';
while ($resultado = mysql_fetch_assoc($query)) {
Your code is getting the first record at the start, and if there's more than one entry, you're then looping through the rest of the records - binning the first one. This way, you're not populating $goto until you know you need it.
It is because you are using up your first record pointer on this line:
$goto = mysql_fetch_array($query);
If you move this line inside the $results == 1 conditional, everything should work fine.
Right now when you get to your while loop, you are starting with the result set pointer already on the second record.
I am sorry about the title as I am not sure whether my problem is in the PHP or the MSSQL query. I am pretty sure it is php.
I am repairing a PHP page that accesses two different MSSQL tables. the page worked fine until we had a system-wide change that created new department ID's and hence some new department names.
I have this almost completely fixed now except one minor thing. When you click List all departments, it Lists all the departments and each link has the correct individuals under them.
The problem is it lists a link for EACH individual in that department name for example if there are 10 people in the Business department we have ten links to Business and all have the same information under them.
I want to make it so there is only 1 link for each department. the two tables are directory (columns involved are Displayname and Department) and departments (columns involved are name and id)
Can someone please tell me where I need to change this so it only prints one link to each department? Is the problem with my SQL query or the PHP?
here is the code
function listDepts() {
$query = "SELECT directory.Lastname, directory.Firstname, directory.email,
directory.phone, directory.Office, directory.Department, departments.id,
departments.name FROM directory FULL JOIN departments ON
directory.Department=departments.id ORDER BY name";
$result = mssql_query($query);
echo "<h3>Please select a department:</h3>\n";
echo "<ul>\n";
for ($i=0; $i<mssql_num_rows($result); ) {
$info = mssql_fetch_assoc($result);
echo "<li>$info[name]</li>\n";
}
echo "</ul>\n\n";
}
Other query
function displayResults($query) {
$result = mssql_query($query);
if (mssql_num_rows($result) > 0) {
for ($i=0; $i<mssql_num_rows($result); $i++) {
$info = mssql_fetch_assoc($result);
if ($info[dept_name] != $last_dept) {
if ($i > 0) {
echo "</table>\n\n";
}
echo "<h3>$info[dept_name]</h3>\n\n";
echo "<table id=\"directory_table\">\n";
echo "<tr>\n";
echo "<th>Name</th>\n";
echo "<th>E-mail</th>\n";
echo "<th>Phone</th>\n";
echo "<th>Office</th>\n";
echo "<th>Title</th>\n";
echo "</tr>\n";
}
if (!$info[dept_name] && $i==0) {
echo "<table id=\"directory_table\">\n";
echo "<tr>\n";
echo "<th>Name</th>\n";
echo "<th>E-mail</th>\n";
echo "<th>Phone</th>\n";
echo "<th>Office</th>\n";
echo "<th>Title</th>\n";
echo "</tr>\n";
}
if ($i % 2 == 0) {
echo "<tr class=\"even\">\n";
} else {
echo "<tr class=\"odd\">\n";
}
echo "<td>";
echo ($info[Firstname]) ? "$info[Firstname]" . " " . "$info[Lastname]" : " ";
echo "</td>\n";
echo "<td>";
echo ($info[email]) ? "$info[email]" : " ";
echo "</td>\n";
echo "<td>";
echo ($info[phone]) ? "$info[phone]" : " ";
echo "</td>\n";
echo "<td>";
echo ($info[office]) ? "$info[office]" : " ";
echo "</td>\n";
echo "<td>";
echo ($info[title]) ? "$info[title]" : " ";
echo "</td>\n";
$last_dept = $info[dept_name];
}
echo "</table>\n\n";
} else {
echo "<p>No results found.</p>\n\n";
}
}
If you're only using these two fields:
echo "<li>$info[name]</li>\n";
Why not just make your select query:
SELECT DISTINCT
name
FROM
departments
ORDER BY
name
You're not using anything from the directory table, so you don't need to take anything from it.
If you've got multiple departments, try:
echo "<li>$info[name]</li>\n";
And then updating your department code to search for employees in the department with that name.
Department code:
$theSQL = "SELECT * FROM directory WHERE department IN (SELECT id FROM departments WHERE name='$department') ORDER BY Lastname");
In your for loop at the end of each iteration $i needs to be evaluated.
It should be like
for ($i=0; $i<mssql_num_rows($result); $i++)
Another way (generally) of looping is
$query = mssql_query('your_query');
while ($row = mssql_fetch_assoc($query)){
echo "<li>$row['name']</li>\n";
}