Loop returning unexpected results - php

Am try to looping through a database result set, the problem is that i know i have only one row of data, yet the loop returns 5 rows
This is my method from my model
function get_latest_pheeds() {
$data = $this->user_keywords($this->ion_auth->user_id);
$keyword = $data;
$user_id = $this->ion_auth->user_id;
foreach($keyword as $key => $word) {
$q = "SELECT *,COUNT(pheed_comments.comment_id) as comments
FROM pheeds
LEFT JOIN pheed_comments ON pheed_comments.P_id=pheeds.pheed_id
WHERE pheed LIKE '%$word%' OR user_id='$user_id'
GROUP BY pheeds.pheed_id
ORDER BY datetime DESC";
$result = $this->db->query($q);
$rows[] = $result->result();
}
return $rows;
}
What am i doing wroing

This is because your query has an OR where it should probably have an AND - each query always matches the user_id='$user_id'.
This loop is quite inefficient anyway, I think you want to do something more like this:
function get_latest_pheeds() {
$keywords = $this->user_keywords($this->ion_auth->user_id);
$q = "SELECT *,COUNT(pheed_comments.comment_id) as comments
FROM pheeds
LEFT JOIN pheed_comments ON pheed_comments.P_id=pheeds.pheed_id
WHERE (pheed LIKE '%".implode("%' OR pheed LIKE '%",$keywords)."%') AND user_id='".$this->ion_auth->user_id."'
GROUP BY pheeds.pheed_id
ORDER BY datetime DESC";
return $this->db->query($q);
}
If you want your results returned as an array like they were previously, you'll need to loop over results and fetch each of them into an array key of another array. I can't do it here because I can't see your db class...
EDIT: Slight fix in the above code...
ANOTHER EDIT: another fix...

Related

PHP inserting array into an object

I am trying to inject an array into an object but it's just not working. This is what I am doing:
1) Get a specific Match record from the database
2) Get all the Player records from the database that are associated with that match
3) Add them players to the Match object
Code:
$matchQuery = "SELECT * FROM matches where new = 1 order by date asc limit 1";
$matchResult = mysql_query($matchQuery,$link) or die('Errant query: '.$matchQuery);
/* create one master array of the records */
$matches = array();
if(mysql_num_rows($matchResult)) {
while($match = mysql_fetch_assoc($matchResult)) {
$playersQuery = "SELECT p.* FROM match_players mp
LEFT JOIN players p on p.id = mp.player_id
WHERE mp.match_id = '$match->id'";
$playerResult = mysql_query($playersQuery,$link) or die('Errant query: '.$playersQuery);
$players = array();
if(mysql_num_rows($playerResult)) {
while($player = mysql_fetch_assoc($playerResult)) {
$match->players[] = $player; //<-- This doesn't seem to work
}
}
$matches[] = $match;
}
}
The objects within Match are being spat out, BUT, the Players are not.
$match is an array, the result of the deprecated mysql_fetch_assoc(). So $match->players[] = $player; is not going to work.
If there is no players key in the sql result, you can add it to the array:
$match['players'][] = $player;
Otherwise you would have to use a different key.
Another problem is your query in the loop: You use $match->id and that should be $match['id'] as $match is an array.
By the way, doing sql queries in a loop is never a good idea, you should try to get your results in one query joining the different tables.
$match["players"] = array();
while($player = mysql_fetch_assoc($playerResult)) {
$match["players"][] = $player;
}

loop through mysql_query and replace value OR 1 query to do work

I am running a sql query, that pulls the id, catid, name, subof from two tables using inner join.
select shop.id, shop.catid, shop.name, shop_cat.catname, shop_cat.subof from shop inner join shop_cat on shop.catid = shop_cat.id where shop.active='1' order by shop_cat.catname, shop.name
Now this results everything i need but I need to loop through the result and do another sql query for the subof value (which is a value, the value being a ID number of the shop_cat). I need to pull the catname of the subof value #, then update the result/array field subof to the name of the cat.
So if the original query gave me a value of 15 for subof, it would do a select catname from shop.cat where id='15' i would take the catname from that query and then update subof = catname for every value in the original result that has a subof value.
EDIT 3/23/13 12:30pm MST: Using more of the code that Opeyemi wrote, to explain more of what I need. I am not sure how else to explain it...
$q = "select shop.id, shop.catid, shop.name, shop_cat.catname, shop_cat.subof from shop inner join shop_cat on shop.catid = shop_cat.id where shop.active='1' order by shop_cat.catname, shop.name";
$r = mysql_query();
while(list($shopid, $catid, $name, $catname, $subof) = mysql_fetch_array($r)) {
$getname = mysql_query("select catname from shop_cat where id='$subof'");
$rowname = mysql_fetch_assoc($getname);
//code to update array to change value of $subof to new $rowname['catname']
}
The DB query runs, gets me my values.
I then need to run a loop of some kind, which will loop through every result PHP aquired from the query. This loop will take the subof value (which is a integer ID number) then run a query to get the value catname of that integer value. Then the loop will update the current result and change the subof value from the integer to the catname pulled from the DB in the loop.
I do not need to update the database at anytime, I need to update the result/array from the first query.
What you need to do is to store the resultset in an array and replace within the array.
$q = "select shop.id, shop.catid, shop.name, shop_cat.catname, shop_cat.subof from shop inner join shop_cat on shop.catid = shop_cat.id where shop.active='1' order by shop_cat.catname, shop.name";
$r = mysql_query();
$dataset = array();
// Store result in an array
while($assoc = mysql_fetch_assoc($r)) {
$dataset[] = $assoc;
}
// Update array
foreach($dataset as $data) {
$getname = mysql_query("select catname from shop_cat where id='{$data['subof']}'");
$rowname = mysql_fetch_assoc($getname);
// replace data
replace_dataset($data['subof'], $rowname);
}
function replace_dataset($key, $newname) {
global $dataset;
foreach($dataset as $k => $data) {
if ($data['id'] == $key)
$dataset[$k]['subof'] = $newname;
}
}
Are you asking how to do this in PHP or what? If you are looking for how to loop results in PHP it is as simple as this
$q = "select shop.id, shop.catid, shop.name, shop_cat.catname, shop_cat.subof from shop inner join shop_cat on shop.catid = shop_cat.id where shop.active='1' order by shop_cat.catname, shop.name";
$r = mysql_query();
while(list($shopid, $catid, $name, $catname, $subof) = mysql_fetch_array($r)) {
// the values from the query are assigned to the variables
// $shopid, $catid, $name, $catname, $subof in that order already
mysql_query("update shop_cat set subof=catname where id='$subof'");
// My interpretation of your query can be wrong though
// But you should get the idea
}
You can use mysql_fetch_assoc() or mysql_fetch_array() or mysql_fetch_row() functions to fetch the row and can put your looping concept on it.
After that you can use mysql_fetch_field() to fetch field subof and id from it.
and update the database after that
You can check the following links
http://www.php.net/manual/en/function.mysql-fetch-array.php
http://www.php.net/manual/en/function.mysql-fetch-assoc.php
http://www.php.net/manual/en/function.mysql-fetch-field.php
I hope you get some idea.

Queries with conditional queries

Let's say i have a query with quite a number of joins and subqueries in one php file that handles queries.
Nb: i put an example of what $query looks like at the bottom
$query = query here;
if ($query) {
return $query->result();
} else {
return false;
}
}
Then in my php file that handles the html, i have the usual foreach loop with some conditions that require making other queries e.g;
Note: result houses object $query->result().
foreach ($results as $item) {
$some_array = array();
$some_id = $item->id;
if ($some_id != 0) {
//id_return_other_id is a function that querys a db table and returns the specified column in the same table, it returns just one field
$other_id = id_return_other_id($some_id);
$some_query = another query that requires some joins and a subquery;
$some_array = the values that are returned from some_query in an array
//here i'm converting obj post into an array so i can merge the data in $some_array to item(Which was converted into an array) then convert all of it back into an object
$item = (object)array_merge($some_array, (array)$item);
}
//do the usual dynamic html stuff here.
}
This works perfectly but as i don't like the way i'm doing lot's of queries in a loop, is there a way to add the if $some_id != 0 in the file that handles queries?
I've tried
$query = query here;
//declaring some array as empty when some_id is 0
$some_array = array();
if ($query) {
if ($some_id != 0) {
//same as i said before
$other_id = $this->id_return_other_id($some_id);
$some_query = some query;
$some_array = array values gotten from some query;
}
$qresult = (object)array_merge($some_array, (array)$query->result);
return $qresult;
} else {
return false;
}
}
This doesn't work for obvious reasons, does any one have any ideas?
Also if there's a way to make these conditions and queries in the $query itself i'd love you forever.
Ps: A demo query would be something like
$sql = "SELECT p.*,up.*,upi.someField,etc..
FROM (
SELECT (another subquery)
FROM table1
WHERE table1_id = 3
UNION ALL
SELECT $user_id
) uf
JOIN table2 p
ON p.id = uf.user_id
LEFT JOIN table3 up
ON .....
LEFT JOIN table4
ON ....
LEFT JOIN table5
ON ....
And so on..etc..
ORDER BY p.date DESC";
$query = mysql_query..
It seems like you just need to run two queries in your query file. The first query would get a broad set of what you’re looking for. The second query would query an id that’s in the result and perform a new query to get any details about that particular id. I use something similar to this in the customer search page for my application.
$output = array();
$query1 = $this->db->query("SELECT * FROM...WHERE id = ...");
foreach ($query->result_array() as $row1)
{
$output[$row1['some_id']] = $row1;
$query2 = $this->db->query("SELECT * FROM table WHERE id = {$row1['some_id']}");
foreach ($query2->result_array() as $row2)
{
$output[$row1['some_id']]['data_details'][$row2['id']] = $row2;
}
}
Then in your page that displays html, you’ll just need two foreaches:
foreach($queryresult as $key=> $field)
{
echo $field['some_field'];
foreach($child['data_details'] as $subkey => $subfield)
{
echo $subfield['some_subfield'];
}
}
I know you’re using objects, but you could probably convert this to use that format. I hope this makes sense/helps.
use this
if ($some_id !== 0) {
instead of
if ($some_id != 0) {

Why does my query return the same row multiple times?

I'm trying to join two tables which share a common id, and it keeps returning a single row multiple times. Am working with codeigniter
This is the function from the model:
function get_latest_pheeds() {
$data = $this->user_keywords($this->ion_auth->user_id);
$keyword = $data;
$user_id = $this->ion_auth->user_id;
foreach($keyword as $key => $word) {
$q = "SELECT *,COUNT(pheed_comments.comment_id) as comments
FROM pheeds
LEFT JOIN pheed_comments ON pheed_comments.P_id=pheeds.pheed_id
WHERE pheed LIKE '%$word%' OR user_id='$user_id'
ORDER BY datetime DESC";
$result = $this->db->query($q);
$rows[] = $result->result();
}
return $rows;
}
Is my query wrong?
You are missing a GROUP BY for your COUNT()
$q = "SELECT *,COUNT(pheed_comments.comment_id) as comments
FROM pheeds
LEFT JOIN pheed_comments ON pheed_comments.P_id=pheeds.pheed_id
WHERE pheed LIKE '%$word%' OR user_id='$user_id'
GROUP BY pheed_id, pheed
ORDER BY datetime DESC";
Now, since you are using SELECT *, there may be more columns returned with the COUNT(). For accurate results, you also must list them in the GROUP BY:
GROUP BY pheed_id, pheed, othercol1, othercol2, othercol3

Order results by count of that row

I'm trying to make a function which will display the top X results of the row Y which I set, for this instance I'm using the row browser and the top 5 results from my table statistics, the where is just to eliminate Search Bot results from showing up. I also want it to return the count of the amount of rows as well. So say there was 10 results for the browser 'Safari', then it would return the count of 10 for that result as well as the result itself.
$display->show_list('statistics', 'browser', '5', 'WHERE browser!=\'Search Bot\'');
Here is my function. I'm cleaned it up a bit to remove certain checks and outputs if the query were to fail, etc.
function show_list($table, $row, $limit = 5, $where = NULL) {
$item = mysql_query("SELECT DISTINCT $row FROM $table $where LIMIT $limit");
$result = array();
while ($fetch = mysql_fetch_array($item)) {
$result[] = $fetch;
}
return $result;
}
Not sure I understand the question, but what about using a group by clause, in your SQL query :
select your_column, count(*)
from your_table
where ...
group by your_column
order by count(*) desc
limit 5
That would get you :
for each value of your_column,
the number of rows with that value
and you'd keep the 5 values of your_column that have the biggest number of rows
Change this line:
$item = mysql_query("SELECT $row, count(*) as rows FROM $table $where GROUP BY count(*) ORDER BY count(*) DESC LIMIT $limit");
After doing that, you may not want to mix this with your generic show_list function.
A random note. DISTINCT tends to be somewhat expensive on the database. I would avoid defaulting to doing it.
Incidentally your indentation is..interesting. No decent programmer will want to work with that code without reformatting to some consistent indentation scheme. There are endless arguments about the best way to format, but the following would be a reasonable indentation of your original code:
function show_list($table, $row, $limit = 5, $where = NULL) {
$item = mysql_query("SELECT DISTINCT $row FROM $table $where LIMIT $limit");
$result = array();
while ($fetch = mysql_fetch_array($item)) {
$result[] = $fetch;
}
return $result;
}
function show_list($table, $column, $limit = 5, $where = '') {
$item = mysql_query("SELECT $column, COUNT(*) AS c FROM $table $where
GROUP BY $column ORDER BY c LIMIT $limit");
$result = array();
while ($fetch = mysql_fetch_array($item)) {
$result[] = $fetch;
}
return $result;
}
Replace row with column - we are actually passing a column name in the variable.
Replace $where = null with $where = '' - it will ensure that the query works correctly even when $where is null.
Modify the query to generate the expected results (to the best of my understanding of your question)
Re-format the code and indent it properly.

Categories