First, I coded this, which looks inside a table, gets the last 10 entries, and displays them. The output is as expected, a list of the 10 last entries in the database.
$query = "SELECT dfid FROM downloads_downloads ORDER BY did DESC limit 10";
$dlresult = mysql_query( $query );
$i=0;
$num = mysql_num_rows ($dlresult);
while ($i < $num) {
$dfid= mysql_result($dlresult,$i,"dfid");
echo "<b>filenumber:</b> $dfid <br>";
++$i;
}
But I don't just need the filenumber. I need the actual filename and url from another table. So I added a select statement inside the while statement, using the file number.
But for some reason, this code only displays one filename instead of 10. I know, from the above code, it's getting all 10 file numbers.
$query = "SELECT dfid FROM downloads_downloads ORDER BY did DESC limit 10";
$dlresult = mysql_query( $query );
$i=0;
$num = mysql_num_rows ($dlresult);
while ($i < $num) {
$dfid= mysql_result($dlresult,$i,"dfid");
$query2 = "SELECT file_name, file_name_furl FROM downloads_files WHERE file_id = '$dfid'";
$dlresult2 = mysql_query( $query2 );
$dlfile_name= mysql_result($dlresult2,$i,"file_name");
$dlfile_name_furl= mysql_result($dlresult2,$i,"file_name_furl");
echo "filenumber: $dfid <br>"; //Shows 10, as expected.
echo "filename: $dlfile_name - $dlfile_name_furl <br>"; //Shows only 1?
++$i;
}
I can manually execute the sql statement and retrieve the file_name and file_name_furl from the table. So the data is right. PHP isn't liking the select within the while statement?
Looks like you're only going to ever have 1 row, in your 2nd select statement, because you are just selecting one row, with your where statement.
So, you're only going to ever have row 0 in the 2nd statement, so its only finding row 0 on the first loop. try instead:
$dlfile_name= mysql_result($dlresult2,0,"file_name");
$dlfile_name_furl= mysql_result($dlresult2,0,"file_name_furl");
However, insrtead of making 11 separate queries, try using just one:
$link = new mysqli(1,2,3,4);
$query = "SELECT downloads_downloads.dfid, downloads_files.file_name, downloads_files.file_name_furl FROM downloads_downloads LEFT OUTER JOIN downloads_files ON downloads_files.file_id = downloads_downloads.dfid ORDER BY downloads_downloads.dfid DESC limit 10;
$result = $link->query($query) ;
if((isset($result->num_rows)) && ($result->num_rows != '')) {
while ($row = $result->fetch_assoc()) {
echo "filenumber: $row['dfid'] <br>";
echo "filename: $row['file_name'] - $row['file_name_furl'] <br>";
}
Read up on mysql joins http://www.keithjbrown.co.uk/vworks/mysql/mysql_p5.php
I'm not sure if this is syntax correct, but it gives you the right idea =)
Related
In the following scenario, $communityPlayerIds is an array of the Id's of people in a community, and $noPlayers is the count of that array.
e.g
$communityPlayerIds = [2,5,6]
$noPlayers = 3
The following function should do the following:
Run an sql query for the number of times represented by $noPlayers, each time retrieving the desired data of a different $communityPlayerId.
At the moment this is creating one new array, players of 24 items, 8 for each player.
public function getCommunityForm($communityId, $noPlayers, $communityPlayersIds){
$returnValue = array();
$i = 0;
foreach ($communityPlayersIds as $cPI){
$sql = " SELECT player1_result, player1_name, date , results_id FROM `results` WHERE player1_id = '".$cPI."' AND community_id = '".$communityId."' UNION ALL SELECT player2_result, player2_name,date, results_id FROM `results` WHERE player2_id = '".$cPI."' AND community_id = '".$communityId."' ORDER BY date DESC Limit 8";
$result = $this->conn->query($sql);
if (mysqli_num_rows($result) === 0) {
$returnValue[] = ['status' => "nil"];
}
if($result != null && (mysqli_num_rows($result) >= 1)){
while($row = $result -> fetch_array(MYSQLI_ASSOC)){
if(!empty($row)){
$returnValue['players'][$i] = $row;
$i++;
}
}
}
}
return $returnValue;
}
What I want is to return a single array, that has within it 3 separate arrays, 1 for each query run.
How do I do this?
Use two separate counters. Use the $i counter for the queries, and another counter for the rows of each query.
In our code, move the increment of $i to the end of the foreach loop, so it gets incremented only one time each pass through that outer loop.
$i = 0
foreach ($communityPlayersIds as $cPI){
$sql = "...";
// process each query
$i++;
}
Within the body of the foreach loop, when you process the rows returned by a query, use another counter for the rows. Initialize before the loop, and increment as the last step in the loop.
And add another dimension to your result array
$rn = 0;
while($row = $result->fetch_array(MYSQLI_ASSOC)){
//
$returnValue['players'][$i][$rn] = ... ;
rn++;
}
EDIT
As Paul Spiegel notes, the $rn counter isn't strictly necessary. An assignment to an array using empty square brackets will add a new element to an array.
while($row = $result->fetch_array(MYSQLI_ASSOC)){
//
$returnValue['players'][$i][] = ... ;
}
First thing I did was simplify your database query (well, I at least made it more efficient) by getting rid of the UNION with the second query.
Next, I set up a prepared statement. This reduces all the overhead of repeated queries to the database. It's been a few years since I worked with mysqli but I believe it should be working, as long as your ID columns are all numbers. I would hope so, but your original code had quotes around them. If they're strings, change iiiii to sssss, and seriously reconsider your database schema (more on that below.)
You don't need a counter since you already have the player ID, just use that as the array index.
public function getCommunityForm($communityId, $noPlayers, $communityPlayersIds){
$sql = " SELECT IF(player1_id=?, player1_result, player2_result) AS result, IF(player1_id=?, player1_name, player2_name) AS name, date, results_id FROM `results` WHERE (player1_id=? OR player2_id=?) AND community_id=? ORDER BY date DESC Limit 8";
$stmt = $this->conn->prepare($sql);
foreach ($communityPlayersIds as $cPI) {
$stmt->bind_param("iiiii", $cPI, $cPI, $cPI, $cPI, $communityId);
$stmt->execute();
if ($result = $stmt->get_result()) {
while($row = $result->fetch_array(MYSQLI_ASSOC)){
$returnValue['players'][$cPI][] = $row;
}
}
}
}
return $returnValue;
}
And for free, here's the PDO version. I'd strongly recommending looking into PDO. It's more modern and less verbose than mysqli. You'll notice no binding of parameters, we get to used named parameters, and getting an array out of it is much easier.
public function getCommunityForm($communityId, $noPlayers, $communityPlayersIds){
$sql = " SELECT IF(player1_id=:pid, player1_result, player2_result) AS result, IF(player1_id=:pid, player1_name, player2_name) AS name, date, results_id FROM `results` WHERE (player1_id=:pid OR player2_id=:pid) AND community_id=:cid ORDER BY date DESC Limit 8";
$stmt = $this->conn->prepare($sql);
foreach ($communityPlayersIds as $cPI) {
if ($stmt->execute([":pid"=>$cPI, ":cid"=>$communityID])) {
$returnValue['players'][$cPI] = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
}
return $returnValue;
}
As for your database schema, you should not have a column for player names in your result table. How many times are names repeated in that table? What if a user wanted to change their name? You should instead have a player table, and then use a join to pull in their details.
Hi im trying to get 5 random rows from a database and then display them. i currently do this but it does result in duplicates.
i need to change the limit to 5 and then store them in an array but how do i do that? or is there a better way?
function GetPlayer($link){
if (isset($_SESSION['username'])) {
$x = 0;
while($x <= 5) {
$sql = "SELECT * FROM userstats ORDER BY RAND() LIMIT 1; ";
$result = mysqli_query($link,$sql);
$row = mysqli_fetch_assoc($result);
if($row['username'] !== $_SESSION['username']){//add so it dosent put duplicates
echo ("<tr>");
echo ("<th>".$row['username']." </th>");
echo ("<th>Level: ".$row['Level']." </th>");
echo ("<th>Player Stats:".$row['Attack']."/".$row['Defence']." </th>");
echo ("<th>Win Chance: ");
echo CalculateWinChance($link,$row['Defence']);
echo ("<th><input type ='submit' name = 'Attack_Btn' value ='Attack'></th>");
echo ("</tr>");
$x++;
}
}
}
}
Why dont't you try to request 5 results (LIMIT 5) AND loop this? It will no return any duplicates. Four queries less would be a side effect.
$sql = "SELECT * FROM userstats ORDER BY RAND() LIMIT 5; ";
while($row = mysqli_fetch_assoc($result)){
...
}
Instead of calling the query 5 times within the loop, you should have a single query. That's the most optimal approach.
You can use GROUP BY clause to select unique rows.
Your query should be like the following:
SELECT *
FROM userstats
GROUP BY username
ORDER BY RAND()
LIMIT 5
You'll want to sanitize the inputs in the query and/or use a prepared statement, but this should get you pretty close to what you want:
$sql = 'SELECT * FROM userstats WHERE username != ? GROUP BY username ORDER BY RAND() LIMIT 5';
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('s', $_SESSION['username']);
How to display only one row at random at the same time from DB. Everything works fine, but all rows are displayed. thanks
<?php
$sql = "SELECT id,name FROM table ";
$rows = array();
$result = $objCon->query($sql);
while($row = $result->fetch_assoc())
{
$rows[] = $row;
}
shuffle($rows);
echo '<ol>';
foreach($rows as $row)
{
echo '<li><h3>'.$row['id'].' = '.$row['name'].'</h3></li>';
}
echo '</ol>';
?>
Change your SQL request:
SELECT id,name FROM table ORDER BY RAND() LIMIT 1;
You can do it using PHP:
....
shuffle($rows);
$randomRow = reset($rows);
....
But the better way is to change your SQL query:
$query = "SELECT id, name FROM table ORDER BY RAND() LIMIT 1;"
<?php
$sql = "
SELECT id, name
FROM table
ORDER BY RAND()
LIMIT 1 ";
$result = mysql_query($sql);
// As you are only return a single row you do you require the while()
$row = mysql_fetch_array($result);
echo '<ol>';
echo '<li><h3>'.$row['id'].' = '.$row['name'].'</h3></li>';
echo '</ol>';
?>
By adding an ORDER BY RAND() in your sql query you are asking MySQL to randomly order the results then at a LIMIT to restrict the number of rows you would like returned.
The example code is written based on selecting a single row. If you would like more, e.g. 5, you will need to add a while loop.
I am making a page that queries a table for all columns of all results ordered by entry time in descending order with a limit. When I query for a count of the rows, the query works just fine, but when I try to query the table again for data, I don't get anything. I decided to try cutting the query down to "SELECT * FROM comments" but I still got no results when "SELECT COUNT(*) AS count FROM comments" just beforehand worked. I've tried using mysqli_error(), but that didn't give me any information.
The query doesn't seem to be failing as the result from mysqli_query() isn't false and when I query in phpMyAdmin, the queries work. A little piece of my code below
//open databases
require_once($root . "databases/data.php");
//get number of suggestions in comments table
$cquery = mysqli_query($cbase, "SELECT COUNT(*) AS count FROM comments"); //this works
$c = mysqli_fetch_array($cquery);
$count = $c["count"];
//get all suggestions
//this query fails
$queryText = "SELECT * FROM comments ORDER BY time DESC LIMIT " . (($page - 1) * $pageLimit) . ", " . $pageLimit;
$query = mysqli_query($cbase, $queryText);
//validate query
if($query === false)
{
$failed = true;
}
//get all comments from query
while(!$failed && $array = mysqli_fetch_array($result))
Please try this on line 3
$c = mysqli_fetch_assoc($cquery);
You can also try like this also,
$c = mysqli_fetch_array($cquery, MYSQLI_ASSOC);
You are just using the wrong variable when reading out your query results in your while-loop. mysqli_fetch_array($result) while you saved the query-result in $query so it should be mysqli_fetch_array($query)
I'm working on a type of spellcheck, autosuggest. I have two dictionaries, one with phrases, and one that should kick in for basic spelling suggestions. Right now I have this on the server side:
$q = strtolower($_GET["q"]);
$q= mysql_real_escape_string($q);
if (!$q) return;
$sql = ("SELECT headings FROM dictionary WHERE headings LIKE '$q%' LIMIT 3");
$rsd = mysql_query($sql);
while($rs = mysql_fetch_array($rsd)) {
$auto = $rs['headings'];
echo "$auto\n";
}
if (mysql_num_rows(mysql_query("SELECT headings FROM dictionary WHERE headings LIKE '$q%' LIMIT 3")) == 0){
$res = mysql_query("SELECT spelling FROM spellcheck WHERE spelling LIKE '$s%' LIMIT 3");
while($result = mysql_fetch_array($res)) {
$spell = $result['spelling'];
echo "$spell\n";
}
}
basically, $s should equal where the first query left off. So if the query was : hello wor. $s would be wor and it would suggest "world" from the mysql_query: $res. I would have to deal with multiple spaces between words too.
Use mysql_affected_rows() to get affected rows of last executed query...
refer http://php.net/manual/en/function.mysql-affected-rows.php