I have 2 tables in my database, table A and table B. I need to populate a visual grid of 20x20 squares, 400 squares in total. I just need to read the data, not insert or update.
What my script does is does FOR loop through each grid id, querys table A to see if data exists, and if it does, it does another mysql query to pulls data from table B.
As you can imagine this is using a lot of resources (400 requests). I'm not the best at PHP, but wondered if anyone knew of a better way to do this?
Note: I can't combine the 2 tables, it has to be separate.
<table width="500" height="500" background="images/map.png"><?
$plot = 1;
for ($plot_y = 1; $plot_y <= 20; $plot_y++) {
echo "<tr>";
for ($plot_x = 1; $plot_x <= 20; $plot_x++) {
$sql_result5 = mysql_query("SELECT * FROM turfs WHERE plot ='$plot'", $db);
if (mysql_num_rows($sql_result5) != 0) {
$rs5 = mysql_fetch_array($sql_result5);
$nogo = 0; // SET COLOR TO rs5[color]
} else {
$nogo = 1;
}
?><td width="23" height="23"><?php
if ($nogo == 0) {
$sql_result = mysql_query("SELECT * FROM properties WHERE plot = '$plot'", $db);
if (mysql_num_rows($sql_result) > 0) {
$rs = mysql_fetch_array($sql_result);
echo "<img src=$rs[image]>";
}
}
echo "</td>";
$plot = $plot + 1;
}
echo "</tr>";
}
?></table>
Obviously that much queries will take a lot of memory. There is a "trick" to optimize multiple queries that are alike - prepared statements.
You have 2 tables thah sounds like you need a join (if you are not using such).
Then you can use some caching if the data is not updating very often.
There are a lot of thing that could be optimized ...
Without knowing your table structure the best we can do is guess at it but following might give you some fresh ideas to work with.
The gist of it would be to
select the GridID's and the related data with one select statement
loop over the results of this statement to fill your grid
SQL Statement (edited)
SELECT t.plot AS plot
, t.plot MOD 20 AS plot_x
, FLOOR(t.plot / 20) AS plot_y
, CASE WHEN p.plot IS NULL THEN 'free' ELSE 'used' END
FROM turfs AS t
LEFT OUTER JOIN properties AS p ON p.plot = t.plot
Related
I am creating a baseball website and I am learning php as I go. I have hit a snag with something I am trying to do; here is what my current code shows:
here is my code:
When I load my files that update the scores, if the game hasn't started the scores are NULL. Is there a code to change it to 0 without having to change it in my database. Any info will be helpful
In your select statement you can use the IFNULL(expr1, 0) function, but you will need to list your columns explicitly instead of using select *. So it would be roughly:
select
game_date,
game_time,
...,
IFNULL(AWAY_SCORE, 0),
IFNULL(HOME_SCORE, 0)
FROM scoreboard;
Yup, by way of PHP. It could also be done in the database query
while($row = $result->fetch_assoc(){
$ascore = $row['score'];
$hscore= $row['score'];
if($ascore == ""){
$ascore = 0;
if($hscore== ""){
$hscore = 0;
}
REST OF YOUR CODE HERE
}
}
I am running a while loop in PHP selecting data from a mysql database. How can i find out what the last record is,
for example:
$sql="SELECT * from table1 ";
$rs=mysql_query($sql,$conn);
while($result=mysql_fetch_array($rs))
{
echo $result["col1"].' - '.$result["col2"].'<br>';
}
then when it gets to the last record i want to display it like:
echo 'Last Record: '.$result["col1"].' - '.$result["col2"].'<br>';
You basically need to record how many rows you have, and then set up a counter. You can do that using mysql_num_rows():
$sql="SELECT * from table1";
$rs = mysql_query($sql,$conn);
$numRows = mysql_num_rows($rs);
$i = 1;
while($result=mysql_fetch_array($rs))
{
echo ($i == $numRows) ? 'Last Record: '.$result["col1"].' - '.$result["col2"].'<br />' : $result["col1"].' - '.$result["col2"].'<br />';
$i++;
}
You should note though that the mysql_*() family of functions is now deprecated. For security and longevity, you really ought to be using MySQLi or PDO.
Get the total count of rows returned and check use a flag variable for the loop iterations and check in loop if flag == total rows
$t=mysql_num_row($rs);
$i=0;
while($result=mysql_fetch_array($rs))
{
$i++;
if($t == $i){
echo "Last Record ";
}
echo $result["col1"].' - '.$result["col2"].'<br>';
}
mysql_num_rows
You can simply use the sql query itself to get the last value, based on whatever ordering you want (or just use DESC to get the bottom of the natural order):
SELECT * FROM table1
ORDER BY your_column DESC
LIMIT 1;
Edit: Since you're looking for the last row, you could check with mysql_num_rows
$numrows = mysql_num_rows($rs);
$i = 1;
// in while loop...
if ($i === $numrows) {
// print last result
} else {
// print normal result
}
$i++;
// end while loop
Essentially, you want a counter for the record you are on and then write when the number of rows is the same as the row number you are on (e.g. the last one)
$sql="SELECT * from table1 ";
$rs=mysql_query($sql,$conn);
$num_rows = mysql_num_rows ($rs);
for ($i=0; $i < $num_rows; $i++) {
$result=mysql_fetch_array($rs);
if ($i == ($num_rows - 1)) {
echo 'Last Record: '.$result["col1"].' - '.$result["col2"].'<br>';
} else {
echo $result["col1"].' - '.$result["col2"].'<br>';
}
}
Future-proof this routine by doing it the "hard way":
while ($next_row = fetch_row(...)) {
if ($prev_row) { do_output($prev_row); }
$prev_row = $next_row;
}
if ($prev_row) { do_output($prev_row, FLAG_IS_LAST_ROW); }
Why? Future maintenance might make mysql_num_rows() unreliable, either because your result set gets too big, or because you want to interface with a variety of SQL backends.
By default, the MySQL client library pulls the entire result set into memory — that is how it knows the number of rows SELECTed without having to count fetches. This behavior is rather convenient for small result sets, but devastating for large result sets. This it is user-configurable. (The options are usually named something like "store_result v. use_result" or "buffered v. unbuffered.")
Additionally, most RDBMS interfaces do not make the size of the result set known in advance. If you want to interface with these some day in a reusable way, you'll need to change your approach.
I'm trying to get a value to be inserted into a table on a webpage if the value equals $i.
$i starts at a number and decreases every loop. i can get it to work but it outputs multiple lines for each $i equivalent to the results in the table
I've reworked the code using everyones feedback to get this.
Echo "<tr><th colspan='3'><center>$rackname</th> </tr>" ;
for ($i=$RUtotal; $i > 0; $i--)
{
echo" <tr class='rackbg'><td class='i'><center>$i</td>" ;
$sql1 = "SELECT racks.rackID, racks.rackname, devices.deviceID, devices.deviceName, racks.rackRU, devices.deviceRU, devices.RUcount
FROM racks LEFT JOIN devices ON racks.rackID = devices.rackID
WHERE devices.rackID = '$rackID'";
$query1 = mysql_query($sql1);
while ($row = mysql_fetch_assoc($query1))
{
$deviceru = $row['deviceRU'];
$deviceID = $row['deviceID'];
$device = $row['deviceName'];
$deviceRUC = $row['RUcount'];
if ($deviceru == $i)
{
echo '<td class="device" rowspan='.$deviceRUC.'><a onclick=window.location="/devices.php?id='.$deviceID.'">'.$device.'</a></td><td rowspan='.$deviceRUC.'></td></tr>';
}
else
{
;
}
}
}
Echo "<tr class='rackb'><th colspan='3'>a</th></tr> " ;
This works to a degree (picture1) but when i add echo "" to the else statement it displays all wrong. (picture 2)
Any help would be greatly appreciated
Picture1 - http://imageshack.us/photo/my-images/263/examplewq.png/
Picture2 - http://imageshack.us/photo/my-images/269/example2jp.png/
I can't quite see what you're trying to do but what it looks like to me is that you want all the items from racks joined with their relevant device and displayed in order of deviceRU. Does this help:
echo "<tr><th colspan='3'><center><b>$rackname</th></tr>" ;
$sql1 = "SELECT racks.rackID, racks.rackname, devices.deviceID, devices.deviceName, racks.rackRU, devices.deviceRU, devices.RUcount
FROM racks LEFT JOIN devices ON racks.rackID = devices.rackID
WHERE racks.rackID = '$rackID' AND devices.deviceRU <= ".intval($RUtotal)."
ORDER BY devices.deviceRU;"
$query1 = mysql_query($sql1);
while ($row = mysql_fetch_array($query1))
{
$deviceru = $row['deviceRU'];
$deviceID = $row['deviceID'];
$device = $row['deviceName'];
$deviceRUC = $row['RUcount'];
echo'<tr class="rackbg"><td class="i">'.$i.'</td><td class="device">'.$device.'</td><td></td></tr>';
}
I've used a LEFT (inner) JOIN in the SQL instead of the outer join that was there before as it'll return less results and might solve your problem. I've ordered the results by deviceRU and only returned results which have deviceRU less than or equal to $RUtotal (as I think the example was showing).
I've also removed the tags, these should be replaced by using CSS to centre either all td elements or centering class="device" and class="i" e.g.:
.device, .i {
text-align: center;
}
I've also swapped your abc to abc which is the correct format for a link.
Could you describe more of the context as it's difficult to see your intention from your post.
Mat
As Peetz said, you don't need nested loop. You need something like:
$i = $RUtotal;
// ...
while ($row = mysql_fetch_array($query1)) {
// ...
if ($deviceru == $i) {
// ...
} else {
// ...
}
// ...
$i--;
}
This is looping $i times, within the outer while loop. This means you are getting the table repeated over and over again.
I suggest you remove the outer while loop.
So right now, I've got a "gallery" system on my homepage of my site. Take a look:
<?php
$objConnect = mysql_connect("mydb.db","hello","mypass") or die(mysql_error());
$objDB = mysql_select_db("mydb");
$pic2 = "SELECT * FROM gallery";
if (!isset($_GET['Page'])) $_GET['Page']='0';
$pic1 = mysql_query($pic2);
$Num_Rows = mysql_num_rows($pic1);
$Per_Page = 16; // Per Page
$Page = $_GET["Page"];
if(!$_GET["Page"])
{$Page=1;}
$Prev_Page = $Page-1;
$Next_Page = $Page+1;
$Page_Start = (($Per_Page*$Page)-$Per_Page);
if($Num_Rows<=$Per_Page)
{$Num_Pages =1;}
else if(($Num_Rows % $Per_Page)==0)
{$Num_Pages =($Num_Rows/$Per_Page) ;}
else
{$Num_Pages =($Num_Rows/$Per_Page)+1;
$Num_Pages = (int)$Num_Pages;}
$pic2 .=" order by GalleryID ASC LIMIT $Page_Start , $Per_Page";
$pic1 = mysql_query($pic2);
$cell = 0;
$link2 = "SELECT * FROM gallery";
$link1 = mysql_query($link2);
$link = mysql_fetch_array($link1);
$alt2 = "SELECT * FROM gallery";
$alt1 = mysql_query($alt2);
$alt = mysql_fetch_array($alt1);
echo '<div id="tablediv"><table border="0" cellpadding="17" cellspacing="0" class="table"><tr>';
while($pic = mysql_fetch_array($pic1))
{if($cell % 4 == 0) {
echo '</tr><tr>';}
if($cell == 2) {
echo '<td>reserved cell, ignore this</td>';
} elseif ($cell == 3) {
echo '<td>reserved cell, ignore this</td>';
} else {
echo '
<td><div class="image"><img src="https://s3.amazonaws.com/images/' . $pic["pic"] . '" alt="' . $alt["alt"] . ' /></div></td>'; }
$cell++;
}
echo '</tr></table></div>';
?>
Anyhow... as you can see, with this system, whenever I insert a new record, it automatically updates my gallery. Now my question is how can I make it so when I insert a new record, it doesn't just affect my homepage gallery, it affects the galleries on the other subsections of my website as well.
Say my site is called site.com . I also have a site.com/nature . My site.com/nature is only for nature photos, but I don't want to manually update /nature by creating a whole new set of table and update that manually. Rather I'd rather take an easier route, so in my gallery table, I can specify whether or not I want it in /nature.
I presume I would need another column (obviously) for specifying what other folders do I want my record to appear in, or maybe some conditional statements to determine which subfolder should my record also appear in and not just my homepage. Unfortunately, I'm a nooblet, so I'm asking if fellow stackers can help me with this. Thanks!
I'm not sure of the exact schema you're using but if your gallery is sub divided into categories like nature, animation. its best to have one extra column ("category") probably a varchar or string (sorry not familiar with exact types in mysql) that specifies the category, so in the nature category you would go like:
select *
from gallery g
where g.category = 'nature'
So if you have another category like pokemon you would go:
select *
from gallery g
where g.category = 'pokemon'
This way you can have many different categories for you site.
but in the main page where you want all the pictures just have:
select *
from gallery g
Also, its best that instead of returning * you return only the fields you actually need. And possible use select DISTINCT filndName so you're not getting repeats the same tuple (entry) when grabbing it from sql
There are a couple of different ways you can go about this. Since you don't want to create another table, one way you can approach it is to use a column of the SET data type. This would allow you to create a set of all the subsections you have (up to 64) with one gallery item being possibly in multiple subsections.
The possible problems are the limit of 64 subsections, of course, and the fact that adding a new subsection requires an ALTER statement which, depending on how you go about adding a subsection, could cause permission issues among other things.
In my opinion, a better way is to add two new tables. One table will be a subsection table which only needs an id and a subsection path ('nature'). The other table will be a gallery-subsection table that has the gallery id and subsection id so that one gallery item can be in multiple subsections. This is not only easier to add a new subsection, but it also allows for many more than 64 subsections.
I would like to have a comment section with replies to comments. The replies will only go one level. For example.
Parent Comment
-- Here is a reply
-- Here is another reply
-- It won't go further than this one tier
My MySQL looks like this:
comment_id, comment, parents_id
if parents_id is 0, it is the parent. if it has a number, that number will correspond to the comment_id, as it will be its child.
now, i've done this crappy code below, but it seems the second loop messes it up and only displays the first div correctly with its children. i believe it is because i'm calling mysql_fetch_row twice...
$query_show_comments = "SELECT * FROM article_comments WHERE article_id = '$article_id'";
$results_show_comments = mysql_query($query_show_comments);
$num_rows_comments = mysql_num_rows($results_show_comments);
for ($i = 0; $i < $num_rows_comments; $i++) {
$comment = mysql_fetch_row($results_show_comments);
echo "<p>comment_id: $comment[0]</p>";
if ($comment[5] == 0) {
echo <<<_HTML
<div class="dispArticle">
<p><strong>Commenter Name commented # 11/22/10 10:10:10pm</strong></p>
<p>$comment[2]</p>
_HTML;
for ($j = 0; $j < $num_rows_comments; $j++) {
$replies = mysql_fetch_row($results_show_comments);
if ($replies[5] > 0 AND $replies[5] == $comment[0]) {
echo <<<_HTML
<div class="comment"><p><strong>Reply Name replied # 11/22/10 10:10:10pm</strong></p>
<p>child_id: $replies[0]</p>
<p>parent_id: $comment[0]</p>
<p>$replies[2]</p>
</div>
<br />
_HTML;
}
}
}
echo "</div>";
}
Been searching for hours and this is what I've found.
Use multiple tables (would like to keep it in one table so less queries)
Use multiple queries (same as above)
Feed into an array first then sort it all out (what if the comments are long and there are a lot? I just did a query AND had to do more server side processing of feeding it into an array, sorting then displaying...)
The problem is that mysql_fetch_row() will always fetch the next row returned by the query, and that could be in any order. For what you are doing to work, you would need a post to be followed immediately by its child comments every time. This is a shaky solution, so I would suggest you use #3 as it is really the same thing as what you are doing.
I also have a couple of suggestions: use mysql_fetch_assoc() over mysql_fetch_row() and use the names of the columns rather than their numbers as this makes the code much more readable and easier to use. You will have to change your query to order by the ascending parent ID to ensure that all parents are set first. Then:
$query = "query";
$result = mysql_query($query);
$comments = array();
while ($row = mysql_fetch_assoc($result)) {
if ($row['parent_id']) {
$comments[$row['parent_id']]['children'][] = $row;
}
else {
$row['children'] = array();
$comments[$row['comment_id']] = $row;
}
}
Now all of the children are associated with parents. Just iterate through the array.
It's not too hard. You should store all comments in one table and have parent_id
parent_id of 0 means it's a comment, parent_id > 0 would point to id of a message in the same table for which it's a reply.
You would also have article_id, just like in your current example.
The trick you need is to do just one SQL select but reference the same table twice.
You sql will be something like this:
SELECT
M.id as id,
M.id as com_mid,
M.post_subject as com_subject,
M.message_body as com_body,
M2.id as rpl_mid,
M2.post_subject as rpl_subject,
M2.message_body as rpl_body,
M2.parent_id
FROM
MESSAGES AS M
LEFT JOIN MESSAGES as M2 on M2.parent_message_id = M.id
WHERE M.article_id = :aid
AND M.parent_id = 0
ORDER BY com_mid ASC,
rpl_mid ASC
Then once you get result of this sql, you will easily figure out how to handle the result array to display messages and replies
You need a second query. Here's an example TRYING to use your code.
$query_show_comments = "SELECT * FROM article_comments WHERE article_id = '$article_id'";
$results_show_comments = mysql_query($query_show_comments);
$num_rows_comments = mysql_num_rows($results_show_comments);
for ($i = 0; $i < $num_rows_comments; $i++) {
$row_comment = mysql_fetch_row($results_show_comments);
echo "<p>comment_id: $row_comment[0]</p>";
if ($row_comment[5] == 0) {
echo <<<_HTML
<div class="dispArticle">
<p><strong>Commenter Name commented # 11/22/10 10:10:10pm</strong></p>
<p>$row_comment[2]</p>
_HTML;
$query_show_replies = "SELECT * FROM article_comments WHERE parent_id = '$article_id'";
$result_replies = mysql_query($query_show_replies);
while( $row_reply = mysql_fetch_row($results_show_comments) ) )
echo "
<div class=\"comment\"><p><strong>Reply Name replied # 11/22/10 10:10:10pm</strong></p>
<p>child_id: $row_reply[0]</p>
<p>parent_id: $row_reply[1]</p>
</div><br />
";
}
}
echo "</div>";
}
You're doing several things in your code that I don't like to do, not saying it can't be don't that way. My advice is to take a more advanced approach to architecting your web applications:
Use while() loops when reading data from queries, it's more error tolerant
don't use the "echo <<<" blocks because it makes code harder to read
technically speaking, you'll want to use htmlspecialchars on all output to a web page, so the <<< shouldn't be used anyways
better yet, use a template system to extricate your markup (view) from your PHP, conside Smarty because it's easy even if performance isn't quite stellar
in fact, while you're at it, consider abstracting your data code into a separate layer
no matter how you get the data, you shouldn't rely on indexed fields when you're using a SELECT *.. because the order could change. What I mean is, instead of using $comment[0] or $comment[1], use $comment['id'] or htmlspecialchars($comment['text'])