I've got a question.
I've got a table table1 like this:
ID | email | first_name | last_name
1 | bla | bladibla | bladibladibla
And with that, I got another table table2:
ID | table1_id | name | value
1 | 1 | foo | bar
2 | 1 | foo1 | bar1
3 | 1 | foo2 | bar2
My question: How do I get the results in php like this?
$array = [
id => 1,
email => bla,
first_name => bladibla,
last_name => bladibladibla,
data => [
[
name => foo,
value => bar
],
[
name => foo1,
value => bar1
],
[
name => foo2,
value => bar2
],
]
]
My solution that works for now, but does not seem the best way to handle it.
I have this now, but it does not seem to be the right way to do it, because in the first foreach loop, it's shooting a query to the db for every row in table1.
$query = "SELECT * FROM `table1`";
$results = $wpdb->get_results($query);
foreach($results as $result) {
$otherQuery = "SELECT * FROM `table2` WHERE `table1_id` = " . $result['id'];
$table2Results = $wpdb->get_results($otherQuery);
foreach($table2Results as $table2Result) {
// save all data in a new array just like I want it.
}
}
Try this :
$query = "SELECT * FROM `table1`";
$results = $wpdb->get_results($query);
$arr = []; // $arr = array();
foreach($results as $result) {
$temp = $result;
$otherQuery = "SELECT * FROM `table2` WHERE `table1_id` = " . $result['id'];
$table2Results = $wpdb->get_results($otherQuery);
foreach($table2Results as $table2Result) {
// save all data in a new array just like I want it.
$temp['data'][] = $table2Result
}
$arr[] = $temp;
}
print_($arr);
$data = array();
$i = 0;
foreach($results as $result)
{
$data[$i] = $result;
$otherQuery = "SELECT * FROM `table2` WHERE `table1_id` = " . $result['id'];
$table2Results = $wpdb->get_results($otherQuery);
$j = 0;
$data[$i]['data'] = array();
foreach($table2Results as $table2Result)
{
$data[$i]['data'][$j] = $table2Result;
$j++;
}
$i++;
}
print_r($data);
$query = "Select
t1.ID,t1.email,t1.first_name,t2.last_name,t2.name,t2.value
From
table1 t1
Inner Join
table2 t2
On t1.ID=t2.table1_id";
$results = $wpdb->get_results($query);
$arr1=[];
$arr2=[];
foreach($results as $result) {
$arr1[]=['id'=>$result['ID'],'email'=>$result['email'],
'first_name'=>$result['first_name'],
'last_name'=>$result['last_name'],'data'=>[]];
$arr2[]=['name' => $result['name'],'value' => $result['value']];
}
$arr1=array_unique($arr1);
$arr1['data'][]=$arr2;
You should be getting duplicates in the JOIN, since your example array shows that each table1 record is related to more than one table2 record. So doing multiple queries isn't going to avoid that. What you want, I think is something like:
$query = "SELECT * FROM table1 LEFT JOIN table2 WHERE table1.id = table2.table1_id";
$results = $wpdb->get_results($query);
foreach($results as $result) {
$table1_id = $result["table1.id"];
$entries[$table1_id]['id'] = $table1_id;
$entries[$table1_id]['email'] = $result["table1.email"];
$entries[$table1_id]['first_name'] = $result["table1.first_name"];
$entries[$table1_id]['last_name'] = $result["table1.last_name"];
$entries[$table1_id]['data'][] = array($result["table2.name"], $result["table2.value"]);
}
print_r($entries) // the full array of table1 entries with the sub-array of table2 entries per table1 entry.
By keying each array entry to the table1.id, you ensure that even when they are repeated, the table2 entries get added as new entries to the data array, while not creating an new array entry for the main "outer" table1 record.
If you don't want the table1.id key on the array itself (and have a simple 0-based indexed array, you could re-index after you are done in the loop like:
$entries = array_values($entries);
Related
I'm trying to remove duplicate results from my SQL query using PHP.
table categories:
id | name
1 | sony
2 | nintendo
table subcategories:
id | name | category_id
1 | playstation | 1
2 | playstation2 | 1
3 | wii | 2
table video_games
id | name | subcategories
1 | grand theft auto | 1,2
2 | super mario | 3
My PHP code:
$query = $database->query('SELECT id FROM subcategories WHERE category_id = "'.$_GET['id'].'"');
while($return = $query->fetch()) {
$subcategories = $return['id'];
$request = '%'.$subcategories.'%';
$game_query = $database->prepare('SELECT * FROM video_games WHERE subcategories LIKE :request');
$game_query->bindValue('request', $request);
$game_query->execute();
if($game_query->rowCount() > 0) {
while($game_return = $game_query->fetch()) {
echo $game_return['name'];
}
}
}
My code works but I have duplicate video games when there have multi subcategories.
I tried using SELECT DISTINCT * FROM video_games WHERE subcategories LIKE :request but same problem.
Any idea to remove duplicate results using SQL or PHP ?
MySql is able to solve this problem by its own means.
Use 'DISTINCT' and 'FIND_IN_SET'.
Like this:
"SELECT DISTINCT
vg.id,
vg.name,
vg.subcategories
FROM
video_games vg
WHERE
FIND_IN_SET( (SELECT id FROM subcategories WHERE category_id='".$_GET['id'])."' , vg.subcategories ) > 0 "
and also you can use array_unique at first save video game names in an array and next remove duplicate value.
.
.
.
your code
.
.
$game_query->execute();
if($game_query->rowCount() > 0) {
$fetch =array_unique($game_query->fetch());
foreach ($fetch as $key => $value){
echo $value;
}
}
test
<pre>
<?php
$arr=array("name"=>"1","name2"=>"2","name1"=>"2","name3"=>"3","name4"=>"1","name5"=>"2","name6"=>"3","name7"=>"22");
print_r($arr);
$fetch =array_unique($arr);
print_r($fetch);
foreach ($fetch as $key => $value)
echo $key."=>".$value."<br>";
?>
</pre>
You can save video game names in an array, and print it afterwards. For example:
$games = array();
$query = $database->query('SELECT id FROM subcategories WHERE category_id = "'.$_GET['id'].'"');
while($return = $query->fetch()) {
$subcategories = $return['id'];
$request = '%'.$subcategories.'%';
$game_query = $database->prepare('SELECT * FROM video_games WHERE subcategories LIKE :request');
$game_query->bindValue('request', $request);
$game_query->execute();
if($game_query->rowCount() > 0) {
while($game_return = $game_query->fetch()) {
if (!in_array($game_return['name'], $games)) {
$games[] = $game_return['name'];
}
}
}
}
//now print the games
foreach ($games as $game) {
echo $game;
}
EDIT If you want more than just 'name', you can expand $games array with $key => $value combination. For example:
. . .
while($game_return = $game_query->fetch()) {
foreach ($games as $game) {
if ($game['name'] === $game_return['name']]) {
continue 2;
}
}
$games[] = array(
'name' => $game_return['name'],
'price' => $game_return['price'],
)
}
And afterwards print it like:
foreach ($games as $game) {
echo $game['name'];
echo $game['price'];
}
How to create a json like this in php;
[{"idorder":"34",
"totalOrder":"55",
"products":[{"idproduct":"5","price":"10"},{"idproduct":"4","price":"45"}]
}]
from table mysql;
+---------+-----------+--------------+
| idorder | idproduct | priceproduct |
+---------+-----------+--------------+
| 1 | 4 | 45 |
| 1 | 5 | 10 |
+---------+-----------+--------------+
my current code something.php;
...
$result = $conn->query($pendientesq);
$return_arr = array();
$productos = array();
$r1=$result->fetch_array();
$return_arr['idorder'] = $r1['idorder'];
$return_arr['totalOrder'] = '55';
//But now????How to create sub array with multiples products.
echo json_encode($return_arr);
you need to try something like this:
$r1=$result->fetch_array();
$return_arr['idorder'] = $r1['idorder'];
$return_arr['totalOrder'] = '55';
// suposse total products are 10
$product=10;
for($i=0;$i<product;$i++){
$return_arr['product'][] = array("idproduct"=>$i,"price"=>$i);//use your price and idproduct.
}
echo json_encode($return_arr);
I don't know how Your table looks like because You've not described it.
But I got for example "orders" table with idorder,idproduct,priceproduct fields.
And wrote this code:
// $q = "SELECT * FROM orders WHERE idorder = 5"; // for single order
$q = "SELECT * FROM orders";
$result = $conn->query($q);
$orders = [];
while($record=$result->fetch_array()) {
if(!isset($orders[$record['idorder']])) {
$orders[$record['idorder']] = [];
$orders[$record['idorder']]['idorder'] = $record['idorder'];
$orders[$record['idorder']]['totalOrder'] = 0;
$orders[$record['idorder']]['products'] = [];
}
$orders[$record['idorder']]['products'][] = ['idproduct' => $recrod['idproduct'],
'price' => $record['priceproduct']];
$orders[$record['idorder']]['totalOrder'] += $record['priceproduct'];
}
$orders = array_values($orders);
echo json_encode($orders);
I have 2 tables that look like this
table A table B
id | data id | features
--------- --------------
1 | blue 1A | 1;2
2 | red 2B | 1;2;3
3 | yellow 3B | 3;1
...... ......
What i plan to do is something like this, where i query one table. loop thru the array of results and explode the data with the semicolon delimiter. then loop thru that new array and query it to get the data (note code below not tested)
$sql = "SELECT * FROM `tableB` WHERE `id`= '2B' LIMIT 1";
$query = $db->query($sql);
while ($row = mysql_fetch_array($query)) {
$arr = explode(';', $row['features']);
for ($i = 0; $i < sizeof($arr); $i++)
{
$sql2 = "SELECT * FROM `tableA` WHERE `id`="'.$arr[$i].'"";
$query2 = $db->query($sql2);
while ($row2 = mysql_fetch_array($query2)) {
$r[] = $row2['data'];
}
}
}
print_r($r);
is there a way i can achieve this just in mysql, where i match the column in tableB with the ID's in tableA? or maybe by not using a nested loop? performance is key. coz both tables have more than 25k rows of data.
thanks in advance
Check out this code. Reduced few loops.
$sql = "SELECT * FROM `tableB` WHERE `id`= '2B' LIMIT 1";
$query = $db->query($sql);
$arr = explode(';', $row['features']);
$str = implode(",", $arr);
$sql2 = "SELECT * FROM `tableA WHERE id IN ({$str});";
$query2 = $db->query($sql2);
while ($row2 = mysql_fetch_array($query2)) {
$r[] = $row2['data'];
}
What you are looking for is the IN function
This will take an array of id's and give you every result in a single query.
So your code should look like this after you apply it
while ($row = mysql_fetch_array($query)) {
$new_query = str_replace(";", ",", $row['features']);
$sql2 = "SELECT * FROM `tableA` WHERE `id` IN ($new_query)";
$query2 = $db->query($sql2);
while ($row2 = mysql_fetch_array($query2)) {
$r[] = $row2['data'];
}
}
How to simplify these steps? The php/sql code aims at deleting party_id's from one table that are not present in another table:
// party_id from one table
$array1 = array();
$db->setQuery("SELECT DISTINCT(record) FROM table1");
$contents = $db->loadObjectList();
foreach( $contents As $content ){
$row = $content->record;
$array1[] = $row;
}
// get party_id from different table
$array2 = array();
$db->setQuery("SELECT DISTINCT(party_id) FROM table2 WHERE user_id = '$id'");
$contents = $db->loadObjectList();
foreach ( $contents As $content ) {
$row = $content->party_id;
$array2[] = $row;
}
// Compare, then delete records existing in array2, but not in array1
$result = array_diff($array2, $array1);
foreach ( $result As $rslt ) {
$db->setQuery("DELETE FROM table2 WHERE party_id = '$rslt' AND user_id = '$id'");
$db->query();
}
Have you looked at using a sub query to delete these records? You could use the WHERE NOT EXISTS clause to delete non-duplicate rows
http://docs.oracle.com/cd/E17952_01/refman-5.5-en/exists-and-not-exists-subqueries.html
DELETE FROM table2
WHERE party_id in (SELECT DISTINCT(party_id) FROM table2 WHERE user_id = '$id')
and party_id not in (SELECT DISTINCT(record) FROM table1)
AND user_id = '$id'
Using not exists:
DELETE
FROM
table2 AS t2
WHERE
NOT EXISTS (SELECT 1 FROM table1 AS t1 WHERE t1.party_id = t2.record)
AND
t2.user_id = '$user_id';
I have a sql database with table "profile_values" (yes, it's a Drupal db), and I would like to pull the user's name, title and company id with one query. (I have done this in the past with three queries, but I'd like to do it in one.)
| fid | uid | value
| 4 | 100 | john
| 8 | 100 | doe
| 9 | 100 | web developer
| 22 | 100 | D3239GE77
I used different field id's (fid) to show that there can be field id's between the rows that I want to pull, but the field id will not change, so 4 will always be first name, 8 would be last name, 9 would be title, and 22 would be company id.
MY FIRST ATTEMPT:
$result = mysql_query("SELECT value FROM profile_values WHERE uid = '$uid' ORDER BY fid ASC");
while($row = mysql_fetch_array($result)) {
$userinfo[] = $row['value'];
$firstname = $userinfo[0];
$lastname = $userinfo[1];
$title = $userinfo[10];
$companyid = $userinfo[12];
}
But this method won't work, because, depending on the optional fields that users will have filled out, there may be more or less fields between.
I need a way to say, "In this array, if fid = 4, $firstname = value
$result = mysql_query("SELECT fid, uid, value FROM profile_values WHERE uid = '$uid' ORDER BY fid ASC");
$user = array();
while ($row = mysql_fetch_array($result)) {
switch ($row['fid']) {
case 4:
$key = 'firstname';
break;
case 8:
$key = 'lastname';
break;
case 9:
$key = 'title';
break;
case 22:
$key = 'company_id';
break;
default:
continue 2; // 2 required when using switch inside loop
}
$user[$key] = $row['value'];
}
I would try the following:
$result = mysql_query("SELECT fid, value FROM profile_values WHERE uid = '$uid' ORDER BY fid ASC");
while($row = mysql_fetch_assoc($result)) {
switch ((int)$row['fid']) {
case 4:
$firstname = $row['value'];
break;
case 8:
$lastname = $row['value'];
break;
case 9:
$title = $row['value'];
break;
case 22:
$companyid = $row['value'];
break;
}
}
Then, I would be using isset() to check whether the variables exists, e.g. isset($lastname)
Hope this helps
Here is an approach that do not require a switch statements or ifs. It's based on an array where you previously map the table's fids to the keys on your destination array:
$fieldMap = array(
4 => 'firstname',
8 => 'lastname',
9 => 'title',
22 => 'companyid'
);
$userinfo = array();
$result = mysql_query("
SELECT fid, value
FROM profile_values
WHERE uid = $uid
ORDER BY fid ASC
");
while($row = mysql_fetch_array($result)) {
$fieldKey = $fieldMap[$row['fid']];
$userinfo[$fieldKey] = $row['value'];
}
Below is my original suggestion, where we pivot the results to get a "regular" table format, instead of a property table format:
SELECT
p1.value AS first_name,
p2.value AS last_name,
p3.value AS title,
p4.value AS company_id
FROM profile_values p1
LEFT OUTER JOIN profile_values p2
ON p2.uid = p1.uid
AND p2.fid = 8
LEFT OUTER JOIN profile_values p3
ON p3.uid = p1.uid
AND p3.fid = 9
LEFT OUTER JOIN profile_values p4
ON p4.uid = p1.uid
AND p4.fid = 22
WHERE p1.uid = $uid AND p1.fid = 4
This is more expensive for SQL then the way you're currently doing it, but it will allow you to fetch data from multiple users more easily (just change p1.uid = $uid to, e.g., p1.uid IN (2, 6, 29).