Not looping from 2 tables - php

$sth = $db->prepare("SELECT * FROM users, profile_post WHERE id='$id'");
$sth->execute();
$row = $sth->fetch(PDO::FETCH_ASSOC);
$stuff = array('Published by' => $row['firstname']. " " .$row['lastname'], 'Content profile:' => $row["content"]);
foreach ($stuff as $key => $value) {
echo "$key: $value\n";
}
This code it's not looping, i've been testing this code with return and arrays
How can i fix it?
It just shows one result, I want all of them from the db.

You're only retrieving one result:
$row = $sth->fetch(PDO::FETCH_ASSOC);
This is the only place where you fetch anything (in this case, a single row) from the database.
Your foreach is looping over the $stuff array, which you have defined with content from $row - and it only contains the Published by and the Content profile: keys.
Instead you want to iterate over the actual fetch call:
$sth = $db->prepare("SELECT * FROM users, profile_post WHERE id='$id'");
$sth->execute();
while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
// process each row as you need here
var_dump($row);
}
.. should give you all the rows. BUT. There are two other issue here.
Your SQL query doesn't have a join condition, so you're effectively cross joining users with profile_post, which means that every row in users is joined with every row in profile_post. The total number of rows will the become rows in users * rows in profile_post - this is probably not what you want.
You add the join condition by adding profile_post.user_id = users.id to your WHERE condition.
The second issue is that you're using ->prepare, but you're still using $id when building the query itself. You want to use a placeholder and then give the value when you're executing the statement, supplying the value externally.
$sth = $db->prepare("
SELECT
*
FROM
users, profile_post
WHERE
profile_post.user_id = users.id AND
users.id = :id
");
$sth->execute([':id' => $id]);

Related

get data from two tables and collect them in array and count rows of one table result

I had two tables named fixture_list and OneRecord where fixture_list has 3 columns named Team1, Team2, player whereas OneRecord has columns like Team1, Team2, id, status so here I want to select all the data of fixture_list and put them into array whereas I want to count the number of rows based on this where condition fixture_list.Team1=OneRecord.Team1 and
fixture_list.Team2=OneRecord.Team2 from OneRecord, actually I am not able to distinguish between selecting the data and putting it into the array and counting the number of rows because I just want to count the rows of one record only. I know things like joins and mysqli_multi_query() can be performed but do not know how...I want to perform this thing in single query please help.
<?php
require_once('connect.php');
$sql = "select * from fixture_list";
if($res = mysqli_query($con,$sql)){
$result = array();
while($row = mysqli_fetch_array($res)){
array_push($result,
array('players'=>$row[3],
'team1_name'=>$row[1],
'team2_name'=>$row[2]
));
}
mysqli_free_result($res);
}
echo json_encode (array("list"=>$result));
mysqli_close($con);
?>
You can use a sub_query to do this. I don't understand your question perfectly (try using capitals and punctuation marks), but this should be probably the format to use.
$sql = "SELECT `fixture_list`.`team1_name`,
`fixture_list`.`team2_name`,
(
SELECT count(`OneRecord`.`Team1`) as `total`
FROM `OneRecord`
WHERE `OneRecord`.`Team1` = `fixture_list`.`Team1`
AND `OneRecord`.`Team2` = `fixture_list`.`Team2`
) as `Total_Players`
FROM `fixture_list`
GROU BY `fixture_list`.`id`";
$result = array(); // keep this outside the while loop to ensure the array is made
if($res = mysqli_query($con,$sql)){
while($row = mysqli_fetch_array($res, MYSQLI_ASSOC)){
$result[] = $row;
}
}
This would give you a $result array as follows:
array(
'team1_name' => 'TEAMNAME1',
'team2_name' => 'TEAMNAME2',
'Total_Players' => INTEGER_VALUE
)
The INTEGER_VALUE is the number of rows from the subquery. You can edit the WHERE part of the subquery to your liking
Then you can do this to create a json object:
echo json_encode($result);
This will echo it, which is ideal if you use it with an Ajax function for example.

Inserting result of a table into another table with two foreach loops

I am trying to get the result of a table and insert it into another table. The results are user id's. This code should work, but it doesn't.
$query1 = "SELECT id FROM users";
$select1 = $db->prepare($query1);
$select1->execute(array());
foreach($select as $index => $rs) {
$users = $rs['id'];
// the results are 1,2,3,4,5,6,7,8... (the user id's)
}
// Here below, I want to add the results into another table...
foreach ($users as $row){
$query2 = "INSERT INTO validateuser (userid) VALUES (".$row.")";
$select2 = $db->prepare($query2);
$select2->execute(array());
}
This seems over-complicated to me. Why not let the database do what databases do best - handle data, and perform this in a single insert-select statement?
INSERT INTO validateuser (userid)
SELECT id FROM users
EDIT:
To answer the concern raised in the comments, the 'validated' value could be selected as a literal:
INSERT INTO validateuser (userid, validated)
SELECT id, 'validated' FROM users
As you iterate the results of the first query with foreach($select as $index => $rs), you set $users to the id of each row of the results with $users = $rs['id'];.
At the end of your loop, $users will contain the id of the last row because it's being overwritten each time. It's not iterable (it's an int), so foreach ($users as $row){ doesn't make sense.
You probably meant to do $users[] = $rs['id']; instead. But if you're just inserting them all, you might as well just do it in one query like the other answer suggests.

PHP Get info from another table

How can I get a row's info from another table without having to SELECT each loop?
//get posts from "posts" table
$stmt = $dbh->prepare("SELECT * FROM posts WHERE user_id = :user_id");
$stmt->bindParam(':user_id', $userId);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($result as $row) {
echo $row['post'];
//get poster's full name from "users" table
$stmt = $dbh->prepare("SELECT * FROM users WHERE user_id = :user_id");
$stmt->bindParam(':user_id', $row['poster_id']);
$stmt->execute();
$result2 = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($result2 as $row2) {
echo $row2['full_name'];
}
}
how can I make this code more efficient and faster?
imagine if i have 1000 posts and each is posted by a different user. i need to get the full name of that user that posted the post. right now, i need to SELECT 1000 times because of those 1000 users. it seems so inefficient right now. how can i make it better?
I heard join might work? what are the solutions?
SELECT * FROM posts
JOIN users ON posts.user_id = users.id
WHERE posts.user_id = :user_id.
You are right, joining the users table onto your posts query will be faster.
Something else you can do to increase performance is to cache the results of your query in something like memcache and then clear the cache when a post is added or deleted. That way you don't need to hit your db every time this data is needed.

More efficient way to grab MySQL row populated with single value

Right now I'm trying to set a variable from an SQL response without doing it more than necessary.
The situation is I have a SQL result from a SELECT + JOIN query with a user_id column that has only a single value. The other columns are different per row and I need to loop through them for that data. I was wondering if there was a way to extract the homogeneous value from the user_id column without setting it over and over again to a variable in my while loop.
Code:
#where I would like the $user_id to be set
while($responseArray = $response->fetch_assoc()){
$userId = $responseArray["user_id"]; #what I don't want to do
#other fetching stuff
}
SQL:
SELECT users.username, users.user_id, posts.post_id, posts.post_content, posts.number_comments, comments.comment_id, comments.comment_post_id
FROM users
JOIN posts
JOIN comments
WHERE delete_bit = 0 AND username = "john";
You cannot get away from fetching at least one result row. Even the fetchOne()-type functions do this. But if you only want a single row, why even bother using a loop in the first place?
$result = $db->query(...);
$row = $result->fetchRow();
$value = $row['somefield'];
would be far better than something silly like
$result = $db->query(...);
while($row = $result->fetchRow()) {
$value = $row['somefield'];
break;
}

Run an update on my MySQL table that will replace the contents of 1 field with the contents of another

I am trying to run an update on a MySQL table that will swap the contents of 1 field with the contents of another (both in the same table).
Here is the basic structure of the table:
id SKU related
== === =======
1234 SKU001 1234,8889,2209
5544 SKU855 2209,1234
2209 SKUYYT 5544
What I need to do is swap the related field for the relavent SKU (so that it lists the sku's instead of the id's). So it would end up looking like this:
id SKU related
== === =======
1234 SKU001 SKU001,SKU111,SKUYYT
5544 SKU855 SKUYYT,SKU001
2209 SKUYYT SKU855
So what I'm trying to achieve is the id in the related field would have been replaced with the SKU that relates to that id.
What I'm currently doing is this:
SELECT id, sku FROM my_table
Then looping through all id's with PHP and updating the table like so:
UPDATE my_table SET related = REPLACE(related, '5544', 'SKU855');
This seems to work but I have 9000+ rows and multiple id's in the related column and it's taking hours to complete
Can anyone suggest a better way of achieving this? (Ideally in MySQL)
Many thanks
If you have access to PHP with this update, I would suggest you do the following:
$rows = some_method_to_load_all_rows_from_your_table();
$id_to_sku = array();
// Loop through all rows to cache their SKU numbers and directly associate them to their row's PK.
foreach ($rows as $row) {
$id_to_sku[$row['id']] = $row['SKU'];
}
// Loop through all rows a second time to then break apart, find, and replace the related IDs.
foreach ($rows as $index => $row) {
$related_ids = explode(',', $row['related']);
foreach($related_ids as &$related_id) {
if (isset($id_to_sku[$related_id]]) {
$related_id = $id_to_sku[$related_id]];
} // else the ID couldn't be found.
}
$rows[$index]['related'] = implode(',', $related_ids);
}
// $rows now contains the related string with the SKU numbers instead of ID numbers.
method_to_update_all_rows_with_new_related_value($rows);
Essentially, doing this in raw SQL is going to be very difficult, and you will be left with a very complex query. The best way is to abstract the detecting and replacing of the IDs / SKU numbers into PHP, where this becomes a much easier and more readable platform to work on.
The code loads all rows in the table, then loops through each row to cache it’s ID and SKU number separately.
Then, we loop through each row again, break apart the related field into an array of IDs, replace those IDs with their correct SKU code using the cache we created, and insert them back into $rows.
$rows becomes the new updated table set. From there, it’s a case of creating a giant UPDATE statement, or looping through each row and executing a single UPDATE statement for each one. Looping in PHP and issuing an UPDATE for each row would be slower as making a query has overhead. But you can also implement the loop in SQL, using stored procedure, avoiding the overhead on communication between your application and database.
/*
create my_table_temp with same structure as in my_table
*/
$mapping = array();
$sth = $dbh->prepare("SELECT id, SKU FROM my_table");
$sth->execute();
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach($rows as $row) {
$mapping[$row['id']] = $row['SKU'];
}
$sql = 'insert into my_table_temp(id, SKU, related) VALUES ';
$params = array();
$sth = $dbh->prepare("SELECT * FROM my_table");
$sth->execute();
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach($rows as $row) {
$related = explode(',', $row['related']);
foreach($related as &$val) {
$val = $mapping[$val];
}
$sql .= '(?, ?, ?),';
$params[] = $row['id'];
$params[] = $row['SKU'];
$params[] = implode(',', $related);
}
$sql = rtrim($sql, ',');
$sth = $dbh->prepare($sql);
$sth->execute($params);
/*
update my_table
set related = q.related
from (
select sku, related
from my_table_temp
) q
where my_table.sku = q.sku;
drop table my_table_temp;
*/
When You are asking to do it in mysql , then it would be possible by using CURSOR and dynamic query.
DELIMITER //
CREATE PROCEDURE `all_update`()
BEGIN
DECLARE ids INT;
DECLARE sname VARCHAR(255);
DECLARE finished INTEGER DEFAULT 0;
DECLARE cursor1 CURSOR FOR SELECT id,SKU FROM testing;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN cursor1;
update_table: LOOP
FETCH cursor1 INTO ids,sname;
IF finished = 1 THEN
LEAVE update_table;
END IF;
SET #s = CONCAT('UPDATE testing SET related = REPLACE(related,', ids,', "',sname,'")');
PREPARE stmt1 FROM #s;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END LOOP update_table;
CLOSE cursor1;
END//
Fiddle is http://sqlfiddle.com/#!2/298a7/1

Categories