inner join gives back multiple values - php

I have products, All of these products have for example. An id, name and price. All of these products are connected in the database like this:
Since I don't have 10 reputation... Here is a link to a picture http://puu.sh/oS95c/b7b5b17427.png
What I want to achieve is to have products that are connected to another product show up on the screen using inner join. However instead of getting the connected items back I get back every item of the right column even if they are not connected.
Here is a link to get a better view of the database: http://puu.sh/oSBF2/1af1ce3751.png
$sql = "SELECT AFBEELDING_KLEIN, PRODUCTNAAM, PRIJS
FROM PRODUCT
inner JOIN PRODUCT_GERELATEERD_PRODUCT
ON PRODUCT.PRODUCTNUMMER=PRODUCT_GERELATEERD_PRODUCT.PRODUCTNUMMER_GERELATEERD_PRODUCT";
$result = sqlsrv_query($db, $sql);
$data = sqlsrv_fetch_array($result);
while($data = sqlsrv_fetch_array($result)) {
$big_picture = '<img src="../' . $data["AFBEELDING_KLEIN"] . '"' . 'alt="product">';
$link = '<a href="../productpaginas/' . $data["PRODUCTNAAM"] . '.php"<p> ' . $data["PRODUCTNAAM"] . '</p></a>';
$price = '<h2> €' . $data["PRIJS"] . '</h2>';
echo '<div class="product">';
echo $big_picture;
echo $link;
echo $price;
echo '</div>';
}

Since you immune to questions and don't provide more information, we can only guess.
You might want a m:n link back to the product table itself.
SELECT
p1.PRODUCTNUMMER, p2.AFBEELDING_KLEIN, p2.PRODUCTNAAM, p2.PRIJS
FROM
PRODUCT AS p1
INNER JOIN
PRODUCT_GERELATEERD_PRODUCT AS pgp
ON
p1.PRODUCTNUMMER = pgp.PRODUCTNUMMER
INNER JOIN
PRODUCT AS p2
ON
pgp.PRODUCTNUMMER_GERELATEERD_PRODUCT = p2.PRODUCTNUMMER
;

Related

How to display data one to many relationship using php and mysql

I have a lot of products and each product has many flavour. How can i display one product name with multiple flavor. below is the script that i have tried.
It doesn't display anything. I'm really new to php.
$res = $conn->query("SELECT as_product.p_id,GROUP_CONCAT(as_product_flavour.pfl_prod_id) as flavours FROM as_product
LEFT JOIN as_product_flavour ON as_product.p_id = as_product_flavour.pfl_prod_id
WHERE as_product.p_id = 28 GROUP BY as_product.p_id");
$currGroup = -1;
while($row = $res->fetch_assoc())
{
echo 'Product Name: '.$row['product_name'];
if($row['flavours'] != $currGroup)
{
$currGroup = $row['p_id'];
echo 'Flavour Id: ' . $row['pfl_id'] . '\n';
echo 'Falvour Name: ' . $row['pfl_flavour'] . '\n';
}
}
I would start with a simpler query...
SELECT p.p_id
, f.pfl_prod_id
FROM as_product p
LEFT
JOIN as_product_flavour f
ON p.p_id = f.pfl_prod_id
WHERE p.p_id = 28
...and handle any remaining display issues in the application code, so a simple transformation of your resulting array.

Query database with comment meta

I have a wordpress comment box with 2 custom files, name and country, which get written to the database with the meta_key tag as comment_name and comment_country. What I need to do is display these comments which needs to include the actual comment, as well as the values of the 2 custom fields. I need to query the database as I need to retrieve ALL comments, not just comments for that particular page.
The code I (kind of) have is:
<?php
global $wpdb;
$querystr = " SELECT comment_content FROM $wpdb->comments INNER JOIN $wpdb->commentmeta ON meta_key = 'comment_name'";
$comment_info = $wpdb->get_results($querystr, OBJECT);
echo '<ul>';
// display the results
foreach($comment_info as $info) {
echo '<li class="commentBox"><p>'. $info->comment_content .'</p><h6>'. $info->meta_value .'</h6></li>';
}
echo '</ul>';
?>
As you can probably see, I need to get the comment_content field which is in wp_comments, but also combine that with the meta_value of 2 meta_keys. I obviously haven't figured out how to try and add the second meta_key/value to my code.
Can anybody help me please as I am at my wits end with this!
UPDATE:
I can now query the info I need. I had to use aliases so I can query 2 different meta_keys with corresponding values. The code:
$querystr =
" SELECT * FROM $wpdb->comments, $wpdb->commentmeta AS commentmeta1, $wpdb->commentmeta AS commentmeta2
WHERE $wpdb->comments.comment_ID = commentmeta1.comment_id
AND $wpdb->comments.comment_ID = commentmeta2.comment_id
AND commentmeta1.meta_key = 'comment_name'
AND commentmeta2.meta_key = 'comment_country'
ORDER BY $wpdb->comments.comment_date DESC";
$comment_info = $wpdb->get_results($querystr, OBJECT);
So what I now need to do is reference commentmeta1 and commentmeta2 in my loop to output the 2 different values. The code I am using:
echo '<ul>';
// display the results
foreach($comment_info as $info) {
echo '<li class="commentBox"><p>' . $info->comment_content . '</p><h6>' . $info->meta_value['commentmeta1'] . ', ' . $info->meta_value['commentmeta2'] . '</h6></li>';
}
echo '</ul>';
The meta values don't output as they should, it basically takes the first letter only of my commentmeta2 ('comment_country'), and duplicates it for each instance (pic below). If I query only one meta key I can display the value in my loop fine by simply running $info->meta_value. How can I simply my meta_values as per my query?
How about specifying the columns you need in your SELECT statement:
SELECT comment_content, comment_name, comment_country FROM ...
Then reference them in your HTML as $info->comment_name and so on.
If you need more direction, you need to share the database schemas for your comments tables.
Sussed it! Final working code is as follows:
$querystr = " SELECT comment_content, commentmeta1.meta_value AS comment_name, commentmeta2.meta_value AS comment_country
FROM $wpdb->comments, $wpdb->commentmeta AS commentmeta1, $wpdb->commentmeta AS commentmeta2
WHERE $wpdb->comments.comment_ID = commentmeta1.comment_id
AND $wpdb->comments.comment_ID = commentmeta2.comment_id
AND commentmeta1.meta_key = 'comment_name'
AND commentmeta2.meta_key = 'comment_country' ORDER BY $wpdb->comments.comment_date DESC";
$comment_info = $wpdb->get_results($querystr, OBJECT);
echo '<ul>';
// display the results
foreach($comment_info as $info) {
echo '<li class="commentBox"><p>' . $info->comment_content . '</p>
<h6>' . $info->comment_name . ', ' . $info->comment_country . '</h6></li>';
}
echo '</ul>';
I basically needed to pass the alias into SELECT and assign a new alias which I could reference in my loop.

JOIN in MySQL and relational tables error

I have three tables, "food","member" and "member_food". I'm trying to make an update user page where a collection of tags are prepopulated by the data in "member_food".
I have debugged the ID sending from the previous page which allows me to select the entry I wish to query, ID:4.
$query = "SELECT * FROM `food` left join `member_food` on food.entityid = member_food.food_id WHERE member_id = '$id'";
//Breakfast
$breakfastresult1 = $mysqli->query($query);
echo '<select name="breakfast1">';
while($BreakfastData1 = mysqli_fetch_array($breakfastresult1, MYSQL_ASSOC))
{
echo '<p><option value="' . htmlspecialchars($BreakfastData1['member_food.food_id']) . '">'
. htmlspecialchars($BreakfastData1['member_food.food_name'])
. '</option>'
. '</p>';
}
echo '</select>';
However, the select fields appear to be empty. I think it's not pulling the correct values from my leftjoin table.
Here is an example of my member_food table:
food table:
edit this, first you have a typo (space missing in left + join) second you need to tell from which of the table member_id belong
$query = "SELECT * FROM `food` as f left join `member_food` as mf on f.entityid = mf.food_id WHERE mf.member_id = '$id'";
You can use this to plan your joins correctly. And, as Abdul pointed out, typos are bad ;)

While loop displaying result 3 times

Basicly I'm trying to make a simple news feed but I'm stuck at the moment as my while loop display the result 3 times, why is this? :/
<?php
$sql ="SELECT
*
FROM
news,
admins";
$result = mysql_query($sql);
if(!$result)
{
echo 'Error while selecting from database. Please contact the administration team';
} else {
while($row = mysql_fetch_assoc($result))
{
echo '
<div class="content_news">
<h1>' . $row['news_name'] . '</h1>
<p style="font-size:12px;">Posted by <b>' . $row['admin_name'] . '</b> on ' . $row['news_date'] . '
<p>' . $row['news_description'] . '</p>
read more
</div>
';
}
}
?>
If you'd like to see what I am talking about: http://freewallpaperblog.com/freshrp/
Ignore the last 2(those are static html not php)
your query selects data from 2 tables (news, admins) so it joins every row of 1st table with every row of 2nd table
SELECT * FROM news, admins
i recommend you to use following query
SELECT news.*, admins.admin_name FROM news
INNER JOIN admins ON news.admin_id = admins.id
where admin_id is your correct column name
You either have 3 admins or 3 rows of news. Your query makes a direct multiplication between tables. Try "left join" instead...
SELECT * FROM news
INNER JOIN admins ON admins.id = news.adminid
Or whatever adminid is in the news table.
Try the following query:
SELECT
*
FROM
news
Inner join admins on news.admin_id = admins.id
You made no JOIN statement in your SQL, as someone else has already commented on in your question. It would help if you posted the associated fields you're grabbing, but based on your $row keys, my best guess is the following should work for you (but I can't promise it will without knowing how your database is designed, I can only infer from the variable names):
$sql = "SELECT news.name, news.date, news.description, news.link, admins.name"
. "FROM news"
. "INNER JOIN admins"
. "ON news.name=admins.name"
References:
http://www.w3schools.com/sql/sql_join_inner.asp
http://www.w3schools.com/sql/sql_join_left.asp
http://dev.mysql.com/doc/refman/5.0/en/join.html

MySQL/PHP Eliminating duplicate, non-identical, returns from a MySQL self-join

I have a small database, holding the details of just under 400 ponies. I wish to query that table and return a table showing the pertinant details of each pony, and it's owner's and breeder's names. The data is held primarily like so:
profiles - a table holding all info assigned to each individual pony, including it's sire's and dam's reg numbers, and it's owner's and breeder's DB assigned id's.
contacts - a table for the people's info. Joined as 'owner' and again as 'breeder' in the query below.
prm_* - multiple parameter tables, holding broad details such as colour, breed, etc.
Where I am running into trouble is when trying my first self join: querying the profiles table three times in order to retrieve the names of the sire and dam for each profile, as well as the pony's own name to begin with. When I run the query, it returns duplicate rows for many (not all) profiles. Using DISTINCT eliminated most of these, but the issue remains with the non-identical results, particularly for those ponies where no sire or dam is on record.
I have googled the problem, and it does appear here and there, but I cant quite grasp what happening in the solutions given. I'm not even certain why the problem occurs at all. Can someone please step me through the issue and the solving of it? I'd be most grateful.
My query as it stands (returns 408 results, from only 387 ponies!):
include 'conn.php';
?>
<table class="admin-display">
<thead><tr><th>No:</th><th>Name:</th><th>Sire:</th><th>Dam:</th><th>Age:</th><th>Colour:</th><th>Gender:</th><th>Owner:</th><th>Breeder:</th></tr></thead>
<?php
$i=1;
$sql = mysql_query("SELECT DISTINCT p.ProfileID, p.ProfileOwnerID, p.ProfileBreederID, p.ProfilePrefix, p.ProfileSireReg, p.ProfileDamReg,
p.ProfileGenderID, p.ProfileAdultColourID, p.ProfileColourModifierID, p.ProfileYearOfBirth,
p.ProfileYearOfDeath, p.ProfileLocalRegNumber, p.ProfileName,
sire.ProfileName AS sireName, sire.ProfilePrefix AS sirePrefix,
dam.ProfileName AS damName, dam.ProfilePrefix AS damPrefix,
owner.ContactFirstName AS owner_fname, owner.ContactLastName AS owner_lname,
breeder.ContactFirstName AS breeder_fname, breeder.ContactLastName AS breeder_lname,
BreedGender, BreedColour, BreedColourModifier
FROM profiles AS p
LEFT JOIN profiles AS sire
ON p.ProfileSireReg = sire.ProfileLocalRegNumber
LEFT JOIN profiles AS dam
ON p.ProfileDamReg = dam.ProfileLocalRegNumber
LEFT JOIN contacts AS owner
ON p.ProfileOwnerID = owner.ContactID
LEFT JOIN contacts AS breeder
ON p.ProfileBreederID = breeder.ContactID
LEFT JOIN prm_breedgender
ON p.ProfileGenderID = prm_breedgender.BreedGenderID
LEFT JOIN prm_breedcolour
ON p.ProfileAdultColourID = prm_breedcolour.BreedColourID
LEFT JOIN prm_breedcolourmodifier
ON p.ProfileColourModifierID = prm_breedcolourmodifier.BreedColourModifierID
WHERE p.ProfileName != 'Unknown'
ORDER BY p.ProfileID ASC");
while($row = mysql_fetch_array($sql)) {
$id = $row['ProfileID'];
$name = $row['ProfilePrefix'] . ' ' . $row['ProfileName'];
if ($row['ProfileYearOfDeath'] > 0000) { $age = ($row['ProfileYearOfDeath'] - $row['ProfileYearOfBirth']); }
elseif ($row['ProfileYearOfDeath'] <= 0000) { $age = (date('Y') - $row['ProfileYearOfBirth']); }
$reg = $row['ProfileLocalRegNumber'];
$sire = $row['sirePrefix'] . ' ' . $row['sireName'];
$dam = $row['damPrefix'] . ' ' . $row['damName'];
$colour = $row['BreedColour'];
$gender = $row['BreedGender'];
$owner = $row['owner_fname'] . ' ' . $row['owner_lname'];
$breeder = $row['breeder_fname'] . ' ' . $row['breeder_lname'];
echo '<tr><td>' . $i++ . '</td><td>' . $name . '</td><td>' . $sire . '</td>';
echo '<td>' . $dam . '</td><td>' . $age . '</td><td>' . $colour . '</td><td>' . $gender. '</td>';
echo '<td>' . $owner . '</td><td>' . $breeder. '</td></tr>';
}
echo '</table>';
mysql_close($con);
Use GROUP BY over DISTINCT:
http://msmvps.com/blogs/robfarley/archive/2007/03/24/group-by-v-distinct-group-by-wins.aspx
The problem is going to be in the data - one of the tables that you're joining against has multiple rows on associated to the join key.
I recommend executing the query in stages. Start with the base query (taking out the field list):
SELECT count(*)
FROM profiles AS p
WHERE p.ProfileName != 'Unknown'
And then add the join tables in one at a time until you see the count increase...
SELECT count(*)
FROM profiles AS p
LEFT JOIN profiles AS sire
ON p.ProfileSireReg = sire.ProfileLocalRegNumber
WHERE p.ProfileName != 'Unknown'
You should then be able to see where the duplicate is. If you want to easily see which record is duplicated, you can run this query:
SELECT p.Profile_id, count(*) cnt
FROM profiles AS p
LEFT JOIN profiles AS sire
ON p.ProfileSireReg = sire.ProfileLocalRegNumber
-- (all other joins)
WHERE p.ProfileName != 'Unknown'
GROUP BY p.Profile_id
HAVING count(*) > 1
Then you can look at the details of the duplicated records.

Categories