MySQL join results different in PHP? - php

I have a query:
SELECT * FROM categorys
LEFT JOIN category_info ON categorys.cat_id=category_info.cat_id
WHERE `cat_name` = 'aname'
ORDER BY `cat_order`
When I run this in phpMyAdmin I get an cat_id back regardless of if there is a match in the second table.
However, when I run this query in my PHP code I get a blank cat_id back, as shown by this print_r():
Array ( [cat_id] => [cat_name] => baths [type] => main [cat_order] =>
99 [cat_img] => [display] => 1 [deleted] => 0 [desc_id] => [desc] =>
[text] => )
Why would there be a different result when the query is exactly the same?
EDIT:
My PHP code:
$getcatidsql = "SELECT * FROM categorys
LEFT JOIN category_info ON categorys.cat_id=category_info.cat_id
WHERE `cat_name` = '{$cname}'
ORDER BY `cat_order";
$getcatidresult = $db->query( $getcatidsql );
$catdata = $db->fetchRow( $getcatidresult );
function query() {
$this->query_total++;
if (func_num_args() == 1) {
$sql = func_get_arg(0);
} else {
$args = func_get_args();
for ($i=1;$i<count($args);$i++) if (!is_numeric($args[$i])) $args[$i] = '"'.mysql_real_escape_string($args[$i]).'"';
$sql = vsprintf(array_shift($args),$args);
}
if ($result = mysql_query($sql,$this->db_connection)) {
return $result;
} else {
$this->dberror( $this->db_connection, $sql );
}
}
function fetchRow($result,$type=MYSQL_ASSOC)
{
if($result)
$row = mysql_fetch_array($result,$type);
return $row;
}

I think you must not use select * (also because of same column names in both tables) , but select exactly fields for your needs
select table_name.field, table_name.field2, other_table_name.field1
.. and you'll get right results from both php code and phpmyadmin

I think it is because 'cat_id' is the same field name in both tables => the same index in result array.
Try to modify query like : " Select categorys.cat_id AS category from categorys ..... "

You're SELECTing * from categorys and category_info. They both have a cat_id column. So you'll get two cat_id columns back.
The question is: what does the SQL library/driver you're using do when it encounters two columns with the same name in your SELECT list?
Looks like it's probably overwriting the first one it comes across with the second one... What happens if you use an explicit SELECT list, specifying categorys.cat_id and not bringing in category_info.cat_id?

When you state
When I run this in phpMyAdmin I get an cat_id back
Do you mean that you get a VALUE for cat_id or do you get it as NULL? Because that is what you get with php, a NULL value for cat_id (as you see in print_r it still appears there).
If you don't want to get lines from categorys where there is no existing line in category_info for that category, then you have to use RIGHT JOIN instead of LEFT JOIN.

Related

Finding a value in a php array

I've been banging my head hard over this problem for the last 2-3 days trying to see the problem from as many different angles as possible but to no avail. I'm turning to the SO community for extra perspectives. Below is the code I have which prints all 9 product plans. I'm wanting to find and print the plan with pricing equals or closest to a given user input. How can I do this?
//arrays of productnames
$productnames=array(1=>"Beginner","Advanced","Expert");
//arrays of productlevels
$productlevels=array(1=>"Bronze","Silver","Gold");
//Get The Length of Product Name Array
$planname_array_length=count($productnames);
//Get The Length of Product Level Array
$planlevel_array_length=count($productlevels);
for ($prn=1; $prn <= $planname_array_length; $prn++) {//loop to create plan name indicators
for ($prl=1; $prl <= $planlevel_array_length; $prl++) {//loop to create plan level indicators
$getpoductsql = " SELECT name, level,productNameId,productLevelId,finalProductPrice
FROM (
SELECT wspn.productName AS name, wspl.productLevel AS level, wsp.productNameId AS productNameId, wsp.productPlanLevel AS productLevelId,
ROUND(SUM(`Price`) * 1.12) AS finalProductPrice,
FROM `products` ws
left join product_plan wsp on wsp.productId = ws.wsid
left join product_plan_level wspl on wsp.productPlanLevel = wspl.wsplid
left join product_plan_name wspn on wspn.wspnid = wsp.productNameId
WHERE wspn.productName = '$planname_array_length[$pn]' AND wspl.productLevel = '$planlevel_array_length[$pl]'
)
AS x ORDER BY ABS(finalProductPrice - $compareprice)"
$resultproducts = $conn->query($getpoductsql);
$prodArray = mysqli_fetch_array($resultproducts);
//print array of each plan
$resultArr = array('planNameID' => $prodArray['planNameId'],
'planName' => $prodArray['name'],
'planLevelID' => $prodArray['planLevelId'],
'planLevelName' => $prodArray['level'],
'planPrice' => $prodArray['finalProductPrice'];
//print arrays of products
echo json_encode($resultArr);
}
}
This will output 9 plans as follow :
{"planNameID":"1","productName":"Beginner","productLevelID":"1","productLevelName":"Bronze","productPrice":"15"}
Rather than performing a separate query for each product name and product level, do them all in one query, and let MySQL find the one with the closest price.
$getpoductsql = " SELECT name, level,productNameId,productLevelId,finalProductPrice
FROM (
SELECT wspn.productName AS name, wspl.productLevel AS level, wsp.productNameId AS productNameId, wsp.productPlanLevel AS productLevelId,
ROUND(SUM(`Price`) * 1.12) AS finalProductPrice,
FROM `products` ws
left join product_plan wsp on wsp.productId = ws.wsid
left join product_plan_level wspl on wsp.productPlanLevel = wspl.wsplid
left join product_plan_name wspn on wspn.wspnid = wsp.productNameId
WHERE wspn.productName IN ('Beginner', 'Advanced', 'Expert') AND wspl.productLevel IN ('Bronze', 'Silver', 'Gold')
GROUP BY productNameId, productLevelId
)
AS x ORDER BY ABS(finalProductPrice - $compareprice)"
forgive my formatting, I'm on mobile
Like Amr Berag said above, your result should be the first row returned from your query.
If you have a table like this:
ID value
---- ------
A 7
B 12
C 23
...
You can then SELECT from this table to find the closest to some value, like so:
(Assume your desired value is $VALUE)
SELECT id, value, ABS(value - $VALUE) AS diff
FROM your_table
ORDER BY diff ASC
This will return something like this (say $VALUE is 10):
id value diff
-- ------ ----
B 12 2
A 7 3
C 23 13
...
You can just pick the first row.
You may also be able to add a WHERE clause to only select the row with the least difference using the MIN function:
SELECT id, value, ABS(value - $VALUE) AS diff
FROM your_table
WHERE diff = MIN(diff)
The way you are doing it will produce invalid json, do it like this:
$result=array();
for ($prn=1; $prn <= $planname_array_length; $prn++) {
for ($prl=1; $prl <= $planlevel_array_length; $prl++) {
. . . // the other code
//print array of each plan
$resultArr = array('planNameID' => $prodArray['planNameId'],
'planName' => $prodArray['name'], 'planLevelID' => $prodArray['planLevelId'],
'planLevelName' => $prodArray['level'],
'planPrice' => $prodArray['finalProductPrice'];
//print arrays of products
$resul[]=$resultArr;
}//loop1
}//loop2
echo json_encode($result);
you should also add the limit 1 and do the rest in JS in the front end

SQL query to get value from referenced table

I have two tables called mg_product and mg_product_user_property.
In mg_product there are 3 columns: id, title, price as
In mg_product_user_property table product_id corresponds with id column in mg_product table.
So my goal is to get the value of property_id of "15", which in the picture above will be "Mediatek".
This is my SQL:
$sql = "SELECT *
FROM mg_product AS products
INNER JOIN mg_product_user_property AS properties
ON products.id = properties.product_id
WHERE title LIKE '%$search%')";`
PHP:
$resultSet = DB::query($sql);
if ($resultSet->num_rows > 0) {
while ($rows = $resultSet->fetch_assoc()) {
$title = $rows['title'];
$price = $rows['price'];
}
} else {
$output = "No results";
}
Now I need to assign to a php variable the value of property_id=15 so I will be able to print "Mediatek" on my website. How can I achieve that? Sorry for my English.
You are pretty close to what you want, but a couple things are going to either be a mess, or unwanted. So, since there are different ways one can go with this, I will only present a very stripped example (and am INTENTIONALLY leaving out a bunch of code here).
You may not want to do a JOIN like that in the initial search, as for each property, it will also return another of the same product. So looping through that will result in dozens of the same product.
However, if _ALL_YOU_WANT_ is to show the Product Title, Price, and Property 15... you can reduce some headwork with a simpler query:
SELECT p.title, p.price, pr.value
FROM mg_product AS p
LEFT JOIN mg_product_user_property AS pr
ON p.id = pr.product_id AND pr.property_id = 15
WHERE p.title LIKE '%$search%'
The LEFT JOIN means if the property doesn't exist, it will still return the product. But with an empty property value. And this should not return dozens of the same product for every other property in the table.
--
The OTHER way you could go about doing it, using the SQL query you already have (and the dozens of results of the same product it will return), you can alter your php loop like so:
$found_products = array();
while ($row = $resultSet->fetch_assoc()) {
if ($row['property_id'] == 15) {
$found_products[$row['product_id']] = array(
'title' => $row['title'],
'price' => $row['price'],
'prop' => $row['value']
);
}
}
// now you have a clean array of found products that have the property
--
Also I am forced to point out that you should use a prepared statement here, replacing inserting $search directly into the code. But showing you all of how to do that is beyond the scope of this question/answer.

LEFT JOIN only returns one row from right table

I have the following query;
"SELECT goals_challenges.*,
products_services.id as psid,
products_services.url,
products_services.feature_benefit
FROM goals_challenges
LEFT JOIN products_services ON goals_challenges.id = products_services.goal_challenge_id
WHERE persona_id = :persona_id"
Both tables have an 'id' column, hence the 'psid' alias.
However, despite there being two records that match the goal_challenge_id in the products_services table, only the first row is returned as part of the result set.
EDIT: Proper Data
goals_challenges
id persona_id title item_category solution
173 14 Lead Gen business challenge advertising
products_services
id goal_challenge_id url feature_benefit
1 173 www.testurl.com good for testing, mobile
2 173 www.google.com good for searching, well known
PHP code, including query;
public function findByPersonaId($persona_id)
{
try {
$this->dblayer->beginTransaction();
$stmt = $this->dblayer->prepare("SELECT goals_challenges.*, products_services.id as psid, products_services.url, products_services.feature_benefit from goals_challenges LEFT JOIN products_services ON goals_challenges.id = products_services.goal_challenge_id WHERE goals_challenges.persona_id = :persona_id");
$stmt->bindParam(':persona_id', $persona_id);
$stmt->execute();
$this->dblayer->commit();
$result_set = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$result_set[] = $this->mapObject($row);
}
return $result_set;
} catch (PDOException $e) {
$this->dblayer->rollBack();
echo $e->getMessage();
exit;
}
}
public function mapObject(array $row)
{
$entry = new GoalChallenge();
$entry->setId($row['id']);
$entry->setPersonaId($row['persona_id']);
$entry->setTitle($row['title']);
$entry->setItemCategory($row['item_category']);
$entry->setDescription($row['description']);
$entry->setSolution($row['solution']);
$entry->setProductService(new ProductService($row['psid'], $row['id'], $row['url'], explode(',', $row['feature_benefit'])));
$entry->SetResearchChecklist($row['research_checklist']);
$entry->setSubtopics($row['subtopics']);
$entry->setKeywords($row['keywords']);
$entry->setStatus($row['status']);
return $entry;
}
What I get returned
Array
(
[id] => 173
[persona_id] => 14
[title] => Lead Gen
[item_category] => Business Challenge
[solution] => Advertising
[product_service] =>
[research_checklist] => 0,0,0,0,0,0
[psid] => 1
[url] => www.google.com
[feature_benefit] => good for testing, mobile
)
EDIT: OK so I've worked out the result I am expecting is there, it's just not in the same goalChallenge object as the other - something in the PHP clearly - any ideas?
I get all the data from the goals_challenges table but only the first row (id 1) from the products_services table.
Is there a problem with my query? I have tried adding "GROUP BY goals_challenges.id" but it doesn't change the result.
Your query looks fine.
In ON condition , Column :- "goal_condition_id" has primary key or not.
Check , if both the columns have primary key.
Thanks
Aman
"SELECT gc.*,
ps.id as psid,
ps.url,
ps.feature_benefit
FROM product_services ps
LEFT JOIN goals_challenges gc ON gc.id = ps.goal_challenge_id
WHERE ps.persona_id = :persona_id"
Since your goal_challenges table has 1 row you are trying to find any proper match with product_services table. But only one row,
Select means distinguish rows for me under these conditions and
restrictions not duplicate rows for me.

Display records from one part of the query first, followed by the records mathching the second part

I have this query:
$result = mysql_query("SELECT id,pic0,bio,url FROM ".$table." WHERE id LIKE '%custom%' || ( category IN ('cat1') AND model = 'bmw'");`
And I am displaying them in a loop like:
while ($slice = mysql_fetch_assoc($result)){ }
Is there a way to firstly display the records from: WHERE id LIKE '%custom%'
And after display the records from: || ( category IN ('cat1') AND model = 'bmw'");
Ty for your answer.
Here is an updated sql code which I did to be sure the duplicates are removed automaticly:
(
SELECT 1 AS sort_col, performerid, pic0
FROM `cronjob_reloaded`
WHERE performerid IS NOT NULL
)
UNION (
SELECT 2 AS sort_col, performerid, pic0
FROM `cronjob_reloaded`
WHERE performerid IS NOT NULL
AND category
IN (
'Girl'
)
)
ORDER BY sort_col
And they are not. The first select gets the same result as the select nr two, but mysql shows me all the rows combined.
you could use a union
$result = mysql_query("(SELECT 1 as sort_col,id,pic0,bio,url FROM ".$table." WHERE id LIKE '%custom%') UNION (SELECT 2 as sort_col,id,pic0,bio,url FROM ".$table." WHERE category IN ('cat1') AND model = 'bmw') order by sort_col";
edit: removed the warning about duplicates (according to mysql union docs, dupes are removed automatically), added sort_col to make sure the order is kept.
what about this?
SELECT id,pic0,bio,url
FROM ".$table."
WHERE id LIKE '%custom%' || ( category IN ('cat1') AND model = 'bmw'")
ORDER BY (id LIKE '%custom%') DESC;
I would put the results into two different variables based on a conditional, then output the variables in whatever order you like outside the loop. Because there may be things that might satisfy both parts of the query, the conditional would be what you think is really important to separate. So if it's crucial that the bmw results go last you could do something like:
//In Loop
$model = $slice['model'];
if($model != bmw){
$displayFirst.= $RecordsToDisplay;
}
else{
$displaySecond.= $RecordsToDisplay;
}
//End Loop
echo $displayFirst;
echo $displaySecond;

How to get the result of a query with values in a array?

This is my function where i fetch my results from database
function Prof_Viewer($MemberId)
{
$query = $this->db->query("SELECT distinct(t1.dProfileId) as prof
FROM tbl_profile_viewer as t1
JOIN tbl_login as t2
WHERE t1.dProfileViwerId='$MemberId'");
if($query->num_rows > 0)
{
foreach($query->result() as $row)
{
echo $row->prof;//i am receiving many values here
$query1 = $this->db->query("SELECT distinct(t3.dUser_name),t2.dPath,t3.dCreatedDate
FROM tbl_login as t3
JOIN tbl_profile_viewer as t1,
tbl_member_details as t2
WHERE t3.dMember_Id = '$row->prof'
AND t2.dMember_Id ='$row->prof'");
}
return $query1->result_array();
}
}
As commented above i receive many values while echo the variable $row->prof;
say i have values such as 1 2 and 3.......
Even if i have these three values my 'query1' takes only the last value .so i have only one result i want the query to be executed for 1 and 2 also
how to Achieve that
You can just use PHP's explode() to convert your string into an array. For example:
<?php
$str = 'one|two|three|four';
// positive limit
print_r(explode('|', $str));
// gives you an array:
Array
(
[0] => one
[1] => two
[2] => three
[3] => four
)
?>
But I think you would be better off if you learned how to do JOIN's:
http://en.wikipedia.org/wiki/Join_(SQL)
I'm assuming you're using mysqli here.
Result_fetch_array() will do what you want
http://au2.php.net/manual/en/mysqli-result.fetch-array.php

Categories