Need help in mysql RIGHT join - php

here is mytable structure?
table:category
id name
1 x
2 y
table:subproduct
id cat_id name myval
1 1 xyz test
2 1 abc test2
So basically i want to select all values from subproduct for each id of category table and show it in array in php?
here is my PHP code
$sqlnew = "SELECT c.cat_id,c.cat_title,s.sub_id,s.sub_title,s.store_cashback FROM category c JOIN subproduct s ON c.cat_id = s.pid";
$pdo = getDB();
$stmtnew = $pdo->query($sqlnew);
$resultnew = $stmtnew->fetchAll();
var_dump($resultnew);
I am using PHP PDO.

If you want to get all items with a particular category ID, you should do something like this:
$statement = $pdo->prepare("SELECT * FROM subproduct INNER JOIN category " .
"ON category.id = subproduct.cat_id WHERE category.id = :id");
$statement->bindValue(":id", $category_id, PDO::PARAM_INT);
$statement->execute();
$data = $statement->fetchAll();
You could use this to individually fetch each category ID and build an array like this:
$statement = $pdo->query("SELECT id FROM category;");
$ids = $statement->fetchAll(PDO::FETCH_COLUMN, 0);
$data = array();
foreach($ids as $id)
{
$statement = $pdo->prepare("SELECT * FROM subproduct INNER JOIN category " .
"ON category.id = subproduct.cat_id WHERE category.id = :id");
$statement->bindValue(":id", $id, PDO::PARAM_INT);
$statement->execute();
$data[$id] = $statement->fetchAll();
}
print_r($data);
I am not crazy about this because it looks inefficient and I don't like looping through queries. You could also request all the data at once and then rearrange it:
$statement = $pdo->query("SELECT * FROM subproduct");
$data = array();
while($subproduct = $statement->fetch(PDO::FETCH_ASSOC))
{
$id = $subproduct['cat_id'];
if (!isset($data[$id])
$data[$id] = array();
array_push($data[$id], $subproduct);
}
print_r($data);
I don't really like this either because using PHP to sort MYSQL data feels wrong since that is MYSQL's job. I could have requested MYSQL sort the data, but then the data would still need to be broken up into a multi-dimensional array, so I am not sure that helps.

Related

PHP inner join categories

I got stuck on something with PHP.,
I am trying to JOIN two tables
$statement = $database->prepare("SELECT categories.name as category_name ,pages.name as page_name FROM categories INNER JOIN pages ON categories.name = pages.category");
$statement->execute();
$fetch = $statement->fetchAll(PDO::FETCH_ASSOC);
$returnValues = '';
foreach($fetch as $item){
if(isset($returnValue[$item->category_name]){
array_push($returnValue[$item->category_name], $item->page_name);
}else{
$returnValue[$item->category_name][] = $item->page_name;
}
}
echo "<pre>";
print_r($returnValue);
Basically I want to get an array which got the category name and behind it all the pages that belongs to that category. now on this PHP code, I get plenty of array which everyone holds category name and one page.. and I can't sort it out , thanks.
Alias the category name so that you can tell it apart from the page name. This query will select the category name and all columns from table pages.
$statement = $database->prepare("SELECT categories.name AS category_name, pages.* FROM categories INNER JOIN pages ON categories.name = pages.category");
$statement->execute();
$fetch = $statement->fetchAll(PDO::FETCH_ASSOC);
Group each row by category name. Change $row['id'] to whatever you use as the primary ID for table pages.
$categoryPages = array();
foreach ( $fetch as $row ) {
$categoryPages[$row['category_name']][$row['id']] = $row;
}
print_r($categoryPages);
This is modifications to your original code, should basically do what you want, there might be some small syntax changes needed.
$statement = $database->prepare("SELECT categories.name as category_name ,pages.name as page_name FROM categories INNER JOIN pages ON categories.name = pages.category");
$statement->execute();
$fetch = $statement->fetchAll(PDO::FETCH_ASSOC);
$returnValues = '';
foreach($fetch as $item){
if(isset($returnValue[$item->category_name]){
array_push($returnValue[$item->category_name], $item->page_name);
}else{
$returnValue[$item->category_name][] = $item->page_name;
}
}
echo "<pre>";
print_r($returnValue);
Something like this might work for you... I know it is not perfect and there are something thing missing in the query prepare, but it should be enough to get you going.
The compiled array should be formatted the way you want.
$statement = $database->prepare("SELECT categories.name FROM categories");
$statement->execute();
$fetch = $statement->fetchAll(PDO::FETCH_ASSOC);
$compiled = '';
foreach($fetch as $category){
$statement = $database->prepare("SELECT page.name FROM pages WHERE pages.category = $category");
$statement->execute();
$pages = $statement->fetchAll(PDO::FETCH_ASSOC);
foreach($pages as $page)
array_push($compiled[$category], $page);
}
}
echo "<pre>";
print_r($compiled);

Alternate query using if statement in PHP

I'm trying to run an alternate query if the initial query fails (it does because the id I'm searching for in this instance only exists in one of the databases being joined) using an if statement and I've constructed it like so:
<?php
require_once($_SERVER['DOCUMENT_ROOT'].'/php/link_costreport_2013.php');
$id = $_GET['id']; //ID # For page/query
if($query = $link->prepare("SELECT locale.id, locale.provider_num, locale.provider_name, locale.state, locale.city,
finstat_ca.coh_and_banks, finstat_ca.temp_investments, finstat_ca.notes_receivable, finstat_ca.accounts_receivable, finstat_ca.other_receivables,
finstat_ca.afun_and_ar, finstat_ca.inventory, finstat_ca.prepaid_expenses, (finstat_ca.other_cur_assets + finstat_ca.due_from_other_funds) as other_cur_assets, finstat_ca.total_current_assets,
finstat_fa.total_fixed_assets,
finstat_olta.investments, (finstat_olta.dep_on_leases + finstat_olta.due_from_owners_officers + finstat_olta.other_assets) as all_olta, finstat_olta.total_other_assets, finstat_olta.end_assets,
finstat_cl.accounts_payable, finstat_cl.salaries_wages_fees_payable, finstat_cl.payroll_taxes_payable, finstat_cl.notes_loans_payable, finstat_cl.deferred_income, finstat_cl.total_current_liabilities,
(finstat_cl.total_current_liabilities - (finstat_cl.accounts_payable + finstat_cl.salaries_wages_fees_payable + finstat_cl.payroll_taxes_payable + finstat_cl.notes_loans_payable + finstat_cl.deferred_income)) as all_other_cl,
finstat_ltl.mortgage_payable, finstat_ltl.notes_payable, finstat_ltl.unsecured_loans, finstat_ltl.other_long_term_liabilities, finstat_ltl.total_long_term_liabilities,
finstat_talfb.total_fund_balance, finstat_talfb.total_lia_plus_fb
FROM `locale`
INNER JOIN `finstat_ca`
ON locale.id = finstat_ca.id
INNER JOIN `finstat_fa`
ON locale.id = finstat_fa.id
INNER JOIN `finstat_olta`
ON locale.id = finstat_olta.id
INNER JOIN `finstat_cl`
ON locale.id = finstat_cl.id
INNER JOIN `finstat_ltl`
ON locale.id = finstat_ltl.id
INNER JOIN `finstat_talfb`
ON locale.id = finstat_talfb.id
WHERE locale.id = :id
LIMIT 1")){
} else {
$query = $link->prepare("SELECT id, provider_num, provider_name, state, city
FROM `locale`
WHERE id = :id
LIMIT 1");
}
$query->bindParam(':id', $id);
$query->execute();
$results = $query->fetch(PDO::FETCH_ASSOC);
echo json_encode($results);
Basically it defaults to the single table where the ID does exist and only pulls a couple fields as opposed to the large statement above it. My only issue is that my code here is not working. My JSON only says false when I echo it. It obviously should not.
Is there an error in my code here?
Thanks in advance
:edit: I should note that when I enter an ID that exists in all the tables joined, the correct result (json) is displayed on the page.
I believe the problem is that even if ID does not exist in the first query, the $query variable still has a proper query in it and there is nothing false about it. That's not what you should be if-testing.
I think you should be testing $results.
This shows you the logic.
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . '/php/link_costreport_2013.php');
//ID # For page/query
$id = $_GET['id'];
$sql_1 = "SQL CODE FOR QUERY 1";
$sql_2 = "SQL CODE FOR QUERY 2";
$query = $link->prepare($sql_1);
$query->bindParam(':id', $id);
$query->execute();
$results = $query->fetch(PDO::FETCH_ASSOC);
if (!$results)
{
$query = $link->prepare($sql_2);
$query->bindParam(':id', $id);
$query->execute();
$results = $query->fetch(PDO::FETCH_ASSOC);
}
echo json_encode($results);
However as you can see there are a few lines of code that are repeated inside the if-statement that very similar to code that was just before the if-statement. Perhaps with a loop that loops twice but breaks out if $results is not false would be neater.
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . '/php/link_costreport_2013.php');
//ID # For page/query
$id = $_GET['id'];
$sql[] = "SQL CODE FOR QUERY 1";
$sql[] = "SQL CODE FOR QUERY 2";
foreach ($sql as $sql_query)
{
$query = $link->prepare($sql_query);
$query->bindParam(':id', $id);
$query->execute();
$results = $query->fetch(PDO::FETCH_ASSOC);
if ($results)
{
break;
}
}
echo json_encode($results);
The world is your oyster.

Query inside while loop repeats results from 2 tables

I am not sure if the title expresses the problem accurately or not. Anyways, here is the explanation:
I have 2 tables, the first one holds users IDs, the other one holds their posts.
The fist query selects user IDs from the fist table, and it loop through the second table to find the users (IDs) posts.
The problem is that when the query finds eg. 5 results (user IDs 1, 6, 999.. etc) in the fist table, then it loops 5 times to search in the second table, it shows 5 results even if the real results is 2 post only created by user 1 and 6.
How can I avoid this repeatation?
Here is the code:
$stmt = $conn->prepare('select userid from table where para=?');
$stmt->bind_param('i', $para);
$stmt->execute();
$result = $stmt->get_result();
while( $row = $result->fetch_assoc()) {
$userid = $row["userid "];
$qname = "select postid,title from posts where uid='$userid'";
$result2 = $conn->query($qname);
$row2 = $result2->fetch_array(MYSQLI_ASSOC);
if ($row2 > 0) {
$postid= $row2['postid'];
$title= $row2['title'];
}
echo $postid." ".$title."<br>";
}
Try
$qname = "select postid,title from posts as P left join table as T on T.userid=P.uid where where para=?";
Or
You can store the results in a common array during the loop.
like
$tempResult = array();
while( $row = $result->fetch_assoc()) {
$userid = $row["userid "];
$qname = "select postid,title from posts where uid='$userid'";
$result2 = $conn->query($qname);
$row2 = $result2->fetch_array(MYSQLI_ASSOC);
if ($row2 > 0) {
$tempResult[$userid][] = $row2['postid'];
$tempResult[$userid][] = $row2['title'];
}
}
you can try this query using a JOIN MYSQL.
SELECT u.userid,p.postid,p.title FROM TABLE `user` u
JOIN posts p ON
p.uid = u.userid
WHERE para=?
You can avoid it by only running one query that joins the two tables together. Something like this:
<?php
$stmt = $conn->prepare('select posts.* from table t inner join posts p on t.userid = p.uid where t.para = ? order by uid');
$stmt->bind_param('i', $para);
$stmt->execute();
$result = $stmt->get_result();
while( $row = $result->fetch_assoc()) {
// $row now has userid, and all post details
}
?>

Loop through all the inventory database and join three tables to one array

i have an inventory of cars in splitted in three different tables with each car having the same aut_id on all three tables.
im trying to loop through the cars while ($counter <= $autocount) meaning for every car, and get info from the three tables for each car to display the data like mileage and price
here is my code so far
while ($counter <= $autocount) //ie run for every car
{
$sql = "SELECT * FROM `auto` WHERE `auto_id` > $auto_id AND
`sold` = $soldvalue";
$get = $dbh->prepare($sql);
$get->execute();
$sql1 = "SELECT * FROM `attributes` WHERE `auto_id` > $auto_id AND
`sold` = $soldvalue";
$get1 = $dbh->prepare($sql1);
$get1->execute();
$sql2 = "SELECT * FROM `pictures` WHERE `auto_id` > $auto_id AND
`sold` = $soldvalue";
$get2 = $dbh->prepare($sql2);
$get2->execute();
$attributes =
$auto =
$pictures =
MY FINAL SOLUTION by #RichardA
// Get all the cars, join their attributes and pictures according to
// the `auto_id`
$query = "SELECT * FROM `auto`
INNER JOIN `attributes` ON `auto`.`auto_id` = `attributes`.`auto_id`
INNER JOIN `pictures` ON `auto`.`auto_id` = `pictures`.`auto_id`
WHERE `auto`.`soldvalue` = :soldvalue AND `auto`.`autoid` > :autoid";
// Prepare the query, binding parameters to prevent SQL injections
$getAutos = $dbh->prepare($query);
// Bind the autoid
$getAutos->bindParam(":autoid", $auto_id, PDO::PARAM_INT);
// Bind the soldvalue
$getAutos->bindParam(":soldvalue", $soldvalue, PDO::PARAM_INT);
// Execute the query
$getAutos->execute();
// Fetch all the cars now, only getting an ASSOCIATIVE ARRAY
$autos = $getAutos->fetchAll(PDO::FETCH_ASSOC);
// Loop through each car
foreach($autos as $auto)
{
// Display the cars here
}
You have to fetch all the result by fetching them and store them in variable
$attributes = $get->fetch(PDO::FETCH_ASSOC);
$auto = $get1->fetch(PDO::FETCH_ASSOC);
$pictures = $get2->fetch(PDO::FETCH_ASSOC);
hence
$attribute[keyname / index name / column name] = value
$auto[keyname / index name / column name] = value
$pictures[keyname / index name / column name] = value
This can be done in a single query, try something like this:
// Get all the cars, join their attributes and pictures according to
// the `auto_id`
$query = "SELECT * FROM `auto`
INNER JOIN `attributes` ON `auto`.`auto_id` = `attributes`.`auto_id`
INNER JOIN `pictures` ON `auto`.`auto_id` = `pictures`.`auto_id`
WHERE `auto`.`soldvalue` = :soldvalue AND `auto`.`autoid` > :autoid";
// Prepare the query, binding parameters to prevent SQL injections
$getAutos = $dbh->prepare($query);
// Bind the autoid
$getAutos->bindParam(":autoid", $auto_id, PDO::PARAM_INT);
// Bind the soldvalue
$getAutos->bindParam(":soldvalue", $soldvalue, PDO::PARAM_INT);
// Execute the query
$getAutos->execute();
// Fetch all the cars now, only getting an ASSOCIATIVE ARRAY
$autos = $getAutos->fetchAll(PDO::FETCH_ASSOC);
// Loop through each car
foreach($autos as $auto)
{
// Display the cars here
}
Unlike your queries, these are actually prepared and bound later. This prevents sql injection.
Check the comments on the code to see exactly what the meaning is behind everything.

How to select one row with max(select field) and another (specific field)?

How to select one row with max(select field) and another (specific field)?
Below is my code
1. Get to know max(select field) first
2. Then select all field within the row.
but step 2 doesn't return any thing, wonder know why?
And is there shorter syntax for same result??
Thanks.
$gid = 1;
// get lid
$sth = $db->prepare("SELECT MAX(lid) as lid FROM t WHERE gid = :gid");
$sth->bindParam(':gid', $gid);
$sth->execute();
$arr = $sth->fetch(PDO::FETCH_ASSOC);
print $arr['lid'];
// nothing return??
$lid = $arr['lid'];
$sth = $db->prepare("SELECT * FROM t WHERE gid = :gid AND lid = :lid");
$sth->bindParam(':gid', $gid);
$sth->bindParam(':lid', $lid);
$row = $sth->fetch();
print_r($row);
You could do it in one step with this query:
$sql = "SELECT t.*
FROM t
INNER JOIN (
SELECT MAX(lid) as lid
FROM t
WHERE gid = :gid
) AS x ON t.lid = x.lid";
$sth = $db->prepare($sql);
$sth->bindParam(':gid', $gid);
$sth->execute();
$arr = $sth->fetch(PDO::FETCH_ASSOC);
print_r($arr);

Categories