Left join MySql/PHP - php

Whilst populating a table based on ids and labels from different tables, it appeared apparent there must potentially be a better way of achieving the same result with less code and a more direct approach using LEFT JOIN but i am puzzled after trying to work out if its actually capable of achieving the desired result.
Am i correct in thinking a LEFT JOIN is usable in this instance?
Referencing two tables against one another where one lists id's related to another table and that other table has the titles allocated for each reference?
I know full well that if theres independent information for each row LEFT JOIN is suitable, but where theres in this case only several ids to reference for many rows, i just am not clicking with how i could get it to work...
The current way i am achieving my desired result in PHP/MySQL
$itemid = $row['item_id'];
$secid = mysql_query(" SELECT * FROM item_groups WHERE item_id='$itemid' ");
while ($secidrow = mysql_fetch_assoc($secid)) {
//echo $secidrow["section_id"]; //testing
$id = $secidrow["section_id"];
$secnameget = mysql_query(" SELECT * FROM items_section_list WHERE item_sec_id='$id' ");
while ($secname = mysql_fetch_assoc($secnameget)) {
echo $secname["section_name"];
}
}
Example of the data
Item groups
:drink
:food
:shelf
Item List
itemId, groupId
Group List
groupId, groupTitle
The idea so outputting data to a table instead of outputting "Item & Id Number, in place of the ID Number the title actually appears.
I have achieved the desired result but i am always interested in seeking better ways to achieve the desired result.

If I've deciphered your code properly, you should be able to use the following query to get both values at the same time.
$itemid = $row['item_id'];
$secid = mysql_query("
SELECT *
FROM item_groups
LEFT JOIN items_section_list
ON items_section_list.item_sec_id = item_groups.section_id
WHERE item_id='$itemid'
");
while ($secidrow = mysql_fetch_assoc($secid)) {
//$id = $secidrow["section_id"];
echo $secidrow["section_name"];
}

Related

Wordpress Shortcode: Get data from 3 tables, compare and filter/show (PHP, MYSQL)

I have been trying everything to achieve this task, but it is rather difficult.
I am trying to do this in Wordpress as shortcode.
The shortcode itself is fine, I don't need any help with that, but just the output here which is giving me a difficult time. The Shortcode has an attribute that can be used to show the ID of the list using $listID
As an example, I have 3 database tables.
complete (variables: id, itemID, listID, userID)
item (variables: id, listID, description, creator)
list (id, name)
What I need to do is show a list from a shortcode variable, in this case database id 1 for the list. Then show the items in that list (using listID in item variable as well as wordpress user function to grab the ID of the logged in user and compare it to the creator variable of the item) -- and have the completed marked in there (using itemID, listID and the logged in user to wordpress to compare with the userID).
I tried this for SQL, but it returned nothing
global $wpdb;
$q_checked = $wpdb->prefix.'checked';
$q_item = $wpdb->prefix.'items';
$q_list = $wpdb->prefix.'list';
$q_results = $wpdb->get_results("
SELECT * FROM (($q_item INNER JOIN $q_list ON $q_item.listID = $listID)
INNER JOIN $q_checked ON $q_list.id = $q_checked.listID;
I also tried this with sql but it only shows from the two tables and not the third, and it will show all instead of excluding the completed.
$q_items = $wpdb->prefix.'items';
$q_checked = $wpdb->prefix.'checked';
$q_result = $wpdb->get_results("SELECT $q_items.title, $q_checked.userID FROM $q_items INNER JOIN $q_checked ON $new_items.id = $q_checked.itemID");
I thought about using a foreach, but none of the above would work well with that would it? Since you can only use one result. Maybe if I could do 2 separate foreach, 1 for the items in the list but exclude them if the id of the item matches the itemID in the completed database? Then do another foreach that would show the completed items for that list.
<?php foreach($q_result as $i ) {
$userID = $i->userID;
$itemNAME = $i->title; ?>
<?php if($userID === ''.$current_user->ID.'') { ?> <?php echo $itemNAME; ?><?php }?>
<?php }; ?>
I honestly think I should rethink the entire thing. Maybe I am overcomplicating it?
This is a fairly standard MySQL query:
SELECT i.description, i.creator,
IF(c.id IS NOT NULL, 'Completed', 'Not Completed') AS status
FROM item i
LEFT JOIN complete c
ON c.itemID = i.id AND
c.listID = i.listID AND
c.userID = ?
WHERE i.listID = ?
The ? placeholders represent parameters that you would bind to the current user ID and list ID supplied by your shortcode.
This performs a left join from items to completed items, and checks for a match on all join conditions. If a match is found, then a row will exist in c, and we mark the item as completed. Otherwise, the c.id will be NULL and we mark it as not completed.

How can I solve an problem with two select statements in one query

I want to retrieve og tags with sql in php language but I only get to see 1 result, that is the first one he reads, the other I don't get to see in page source.
this is the code with php.
$query = "SELECT metatitle FROM isacontent_content WHERE contentid = 12245
UNION ALL
SELECT name FROM isacontent_module_anchorimage WHERE contentid = 12245";
$resimage = $conn->query($query);
if(is_array($resimage)){
foreach ($resimage as $resItem){
$metaData[] = $resItem->fetch_assoc();
}
}else{
$metaData[] = $resimage->fetch_assoc();
}
$title = $metaData[0]["metatitle"];
$image = $metaData[0]["name"];
I expect that both select statements will work and I can see both contents in the meta tags
For UNION ALL, your column name must be same or you can use ALIAS for this.
but, here in your example, you can simply use INNER JOIN to get the both values from 2 tables by using 1 single query.
Example:
SELECT ic.metatitle, im.name FROM isacontent_content ic
INNER JOIN isacontent_module_anchorimage im ON im.contentid = ic.contentid
WHERE ic.contentid = 12245
Using INNER JOIN because your both tables having relation, so you can simply use INNER JOIN
Side Note:
If you know, your query will return 1 row then why are you storing data into an array here $metaData[]? you can simply store $title and $image inside you foreach() loop.
When you use union, your columns have to be in same number as it will combine results of two queries. In your case your asking for an particular content results which are stored in multiple tables, so you can go for joins.

I am trying to compare items in two different DB tables

I'm having trouble getting this to work correctly on my classifieds website, but basically what I am doing is taking all from an Item table LIMIT 40 and displaying it on page. Now for the hard part, I am taking all from a category table, which contains the names of the categories (each category name has a relative id). I need to print out the name of the category WHEN its id is equal to the id of the item. Hopefully the code will help clarify:
$sql = mysql_query("SELECT * FROM table_item ORDER BY creationtime DESC LIMIT 40");
$sql2 = mysql_query("SELECT * FROM table_category");
$ad_count = mysql_num_rows($sql);
$row2 = mysql_fetch_array($sql2);
if($ad_count > 0){
while($row = mysql_fetch_array($sql)){
$item_categoryId = $row["cid"];
$categoryId = $row2["id"];
$categoryName = $row2["name"];
while($item_categoryId == $categoryId){
$catName = $categoryName;
}
echo $catName;
}
}
Now, there is a little more to the code then what I put up, I tried to keep this short and sweet. Instead of echoing the category name, its actually being put into an HTML table row and there is also a lot more information being put in as well. Everything works fine when I don't do anything with the category name, but when I try to build something to access and compare it, then everything goes to shit.
Also, I should mention that this nested while loop seemed to be the best way to go about this (I have tried many ways) and the error I am getting for this is that "there is an unexpected '}'".
Use joins instead of nested loops:
SELECT
*
FROM
table_item,
INNER JOIN
table_category
ON
table_item.cid=table_category.id
ORDER BY
creationtime DESC
LIMIT 40
If not every item has a corresponding category, use LEFT JOIN instead of INNER JOIN.

SQL Query Optimization help

my foundation on SQL is pretty weak so I hope you could bear with me. I have three tables: contents, categories, and categorization. The setup was chosen since some content will belong to one or more categories.
I want to fetch contents and its corresponding categories.
This is an overly-simplified version of the current script, without error-checking routines:
$q = "SELECT * FROM contents WHERE contents.foo = 'bar'"
$resource = mysql_query($q);
$categoryFilter = array();
$q2 = "SELECT * FROM categorization WHERE ";
while($content = mysql_fetch_assoc($resource))
{
$categoryFilter[] = "content_id='" . $content["id"] . "'";
}
if(count($categoryFilter))
{
$q2 .= implode(" OR ", $categoryFilter);
mysql_query($q2);
}
That's the gist of it. I hope you get what I am trying to do. I don't know if I can actually use JOINS the content_id may be present in multiple rows in categorization. So what I did was to simply append multiple OR's, trying to fetch items one by one. I really would not like to use multiple queries in this scenario. I hope anyone could suggest an approach
Thanks for your time
One query should be enough to fetch data from all three tables:
SELECT categories.category_id #, other fields
FROM contents
INNER JOIN categorization ON contents.content_id = categorization.content_id
INNER JOIN categories ON categorization.category_id = categories.category_id
WHERE contents.content_id = 1 # AND other filters
Tweak the columns in the SELECT clause and/or conditions in WHERE clause according to your needs.
This should do the same thing as in your example:
$q = "
SELECT *
FROM
contents c
categorization ctg ON ctg.content_id = c.id
WHERE c.foo = 'bar'
";
$result = mysql_query($q);
If I understand it correctly, you can do this in one sql statement
SELECT *
FROM contents t1
JOIN categorization t2
WHERE t1.content_id = t2.content_id AND t1.foo = 'bar'
Also ensure that content_id is indexed both in 'content' and 'categorization'. You may find it worthwhile indexing 'foo' aswell, but it depends on how you are actually searching.

how to query a 1-to-many db relationship and display the rows correctly?

sorry if my question kind of doesn't make sense but i am total confused onto what im trying to accomplish.
here are my tables.
tbl_products(if the image came out small, right click on it and view picture to see it big.)
tbl_product_images
basically tbl_products has the record for a product and its description. and tbl_product_images has the images for this product. i want to display the product title,description, and its images in a format like this.
problem is the query i wrote which is:
select
tbl_products.dealname,
tbl_products.desc,
tbl_products.price,
tbl_products.discount,
tbl_product_images.thumb,
tbl_product_images.large
from tbl_products
inner join tbl_product_images
on tbl_products.pHash = tbl_product_images.pHash where tbl_products.startdate = '2010-12-09';
displays the query like this.
so when i need to write something like this
while($row = mysql_fetch_assoc($query))
{
print $row['dealname'];
print "<img src='".$row['large']."'>";
//and so on.
}
i will see the product displayed 4 times since i have 4 images for this product. what is the best way to perform what i am trying to accomplish? btw, phash is another way of id. its my way of relating a products identification within another table.
You can use the GROUP_CONCAT() function in MySQL if you want to fetch everything in one query, but you'll have to split up the image information using PHP.
Here's an example using | (pipe) as the delimiter between thumb/large image file names.
Query:
select
tbl_products.dealname,
tbl_products.desc,
tbl_products.price,
tbl_products.discount,
GROUP_CONCAT(tbl_product_images.thumb SEPARATOR '|') AS thumbs,
GROUP_CONCAT(tbl_product_images.large SEPARATOR '|') AS images
from tbl_products
inner join tbl_product_images
on tbl_products.pHash = tbl_product_images.pHash
where tbl_products.startdate = '2010-12-09'
group by tbl_products.pHash;
PHP:
while($row = mysql_fetch_assoc($query))
{
print $row['dealname'];
// $thumbs = explode('|', $row['thumbs']);
$images = explode('|', $row['images']);
foreach ($images as $image) {
print "<img src='".$image."'>";
}
}
The easiest and most straightforward way to do this is to make two queries: one for the product, which will get you one row, and another for the photos, which will get you multiple rows.
Trying to do this in one query means you have to de-duplicate the data that you've asked the database to repeat. That's silly.
Create links to a page where you want to view a product's detail by linking to it and passing a qstring parameter along the lines of ?phash=$phash.
On the details page:
Use a SQL query like this one:
SELECT
tbl_products.dealname,
tbl_products.desc,
tbl_products.price,
tbl_products.discount,
tbl_product_images.thumb,
tbl_product_images.large
FROM
tbl_products
INNER JOIN
tbl_product_images
ON
tbl_products.pHash = tbl_product_images.pHash
WHERE
tbl_products.pHash = $detailsProductPHash
$i = 0;
while($row = mysql_fetch_assoc($query))
{
if($i==0) print $row['dealname'];
print "<img src='".$row['large']."'>";
$i++;
//and so on.
}
From what I understand, you want to only display information about the product once, and display the images multiple times. The above will accomplish what you want.

Categories