Select columns from various tables in mySQL - mysql

I have a dynamic list of categories, which is retrieved from mySQL. When the user is clicking on a category, it loads images for that specific category from the DB. This is the function that does it:
function getImages($categoryID)
{
return json_encode(select("SELECT * FROM images WHERE categoryID=$categoryID"));
}
Now I also want to retrieve also the category name again from the "categories" table (to include the name of the selected category in other part of the page). I tried to do this:
function getImages($categoryID)
{
return json_encode(select(
"SELECT categories.categoryName, images.imageFileName, images.imageHeader
FROM images JOIN categories
ON categories.categoryID = images.categoryID
WHERE categoryID=$categoryID"));
}
but that didn't work, now I don't even get the images.
How can it be done?

In your WHERE clause, categoryID is ambiguous.
WHERE categoryID=$categoryID
Since you have two tables with categoryID, you need to identify which one the WHERE should be looking at.
WHERE categories.categoryID=$categoryID
To make life easier for yourself, you might want to consider aliasing your tables, like this:
SELECT c.categoryName, i.imageFileName, i.imageHeader
FROM images i
JOIN categories c ON c.categoryID = i.categoryID
WHERE c.categoryID=$categoryID
Also, which language are you developing in? If this is a web app, you might want to consider escaping $categoryID to protect against SQL injection.

There is an error in the SQL query, categoryID is ambiguous. Try:
SELECT
categories.categoryName,
images.imageFileName,
images.imageHeader
FROM
images
JOIN
categories on categories.categoryID = images.categoryID
WHERE
categories.categoryID=$categoryID;

Rehashing what's already been said, try a left join so that images that aren't categorized don't get filtered out and use an escape such as the following:
$query = "SELECT c.categoryName, i.imageFileName, i.imageHeader
FROM images i
LEFT JOIN categories c
ON c.categoryID = i.categoryID
WHERE c.categoryID= " . intval($categoryID) . ";"

I think you must qualify the field in your WHEREclause with a table name, i.e.
WHERE image.categoryID=$categoryID
The databse engine does not know which of the two categoryID fields you mean. If you run into problems like this again, you should test the query on the MySQL command line. There you get an error message, that is very helpful in fixing your error.

Related

JOINING a query from 2 tables - Multiple Results

Could someone please tell explain to me how to properly process a query that collects information from 2 tables, i thought I had this figured out until I added more records. Please look at the image I have below:enter image description here
(The last record should not have the name "Thomas Murray" in it)
Then there is the query I am processing:
"select a.*, b.forenames, b.surname FROM playerSkills a, playerdb b GROUP BY sheetNo"
What I was hoping to do is collect all from the playerSkills database (which it does) and only bring over the names from the second database (playerdb) that matched with the playerID but as I want to return more than one result so I don't know what to do as it returns the whole column and just pastes the one name into every field.
Though I am sure a JOIN is to be inserted here, I am not sure which or at all.
I am not experienced with SQL but trying to wrap my head around it. I have experimented with the JOIN clauses but didn't get far probably due to a syntax.
How can join the names to the playerID so they appear in the appropriate fields?
You need columns to join on . . . and proper join syntax:
select ps.*, p.forenames, p.surname
FROM playerSkills ps JOIN
playerdb p
ON ps.playerId = p.playerId;
Notes:
Your query does not require GROUP BY.
Your query does require JOIN conditions.
Kudos for using table aliases. They should be abbreviations for the table name.
You want to always use explicit JOIN syntax. No commas in the FROM clause.

Search table based on linked text field from second table

Not being an SQL wiz at all, browsing through the results here, I was unable to find a proper solution, although the problem itself is fairly simple.
Two tables:
products
id
title
strings
id
language_en
An entry in products may look like this:
id = 1
title = 10
Corresponding entry in strings:
id = 10
language_en = "myProduct"
Where as the number in products.title contains the id of a corresponding entry in strings.
I want to search products for a certain title, but those titles are stored in strings (because of multi-language capacities).
This is what i came up with:
SELECT p.* FROM products p JOIN strings s ON p.title LIKE s.language_en WHERE s.language_en LIKE "myProduct"
Unfortunately, this does not yield any proper results. Obviously i have trouble understanding the concept behind the join, but even reading some articles on the concept does not get me there. It's not my pair of shoes.
In your sql condition may be wrong i think, i modified that sql.
select p.* FROM products p JOIN strings s ON p.title = s.id and s.language_en = "Product name"
you can execute and see the result.
Thank you.
The join is wrong - it's comparing p.title to s.language_en instead of s.id which you described should match it.
Also note that when used without a wildcard, the like operator is essentially equivalent to =, and it may make the code easier to read if you use it directly:
SELECT p.*
FROM products p
JOIN strings s ON p.title = s.id
WHERE s.language_en = 'myProduct'

MySQL Join vs Sub query vs?

Looking to avoid a potential problem here for future growth (think hundreds of thousands of records in a table)
I have two tables, one that houses documents and the other categories for these documents. Essentially a document can have many categories. I would like to be able to return all the corresponding categories for a document, sort of like so
doc.id, doc.name, .... , category1, category2
Figure there is two ways to achieve this
a) Join join the tables together using something like this then parse the output. Issue here would be that we replicate the data for the document for as many categories as it belongs to
SELECT id, name, ..., category
FROM doc
LEFT OUTER JOIN category ON (doc.id = category.docId)
b) Sub Query use a suq query to concatenate all the categories together. Issue here is a potential performance issue
SELECT
id, name, ....
(SELECT group_concat(category,',') FROM category where category.docId = doc.id) as category
from doc
OR any other ideas that might work better, keeping performance in mind?
create a view, which could be initially solution a) but it could be changed in the DB later to solution b) or c) if necessary. This way no client code should need to change.

MySQL joins confuse me and I always get syntax errors

I need to fetch some data from a MySQL db. I have the function working using two separate, simple queries, but i'm sure this is probably achievable with one query using a JOIN. SQL isn't my strong point and I keep getting syntax errors when I try. Sure, I could leave it as it is, why not, it works. But i would prefer to see a real world example of how they can be joined so i can try and apply it on other queries in the future.
Query one is:
select manufacturers_id from products where products_name = product a
The result is then put into a variable and used in the following
select manufacturers_name from manufacturers where manufacturers id = $man_id
So, basically, the products table holds the manufacturers_id, which we need to collect for a given product to find out what the manufacturers name is from the manufacturers table.
manufacturers_id is the common field.
Try this:
SELECT b.manufacturers_name
FROM products a
LEFT JOIN manufacturers b ON a.manufacturers_id = b.manufacturers_id
WHERE a.products_name = 'PRODUCT NAME'
Below is a diagram of SQL Joins
Image Source
Try this:
select m.manufacturers_name from products p, manufacturers m
where p.products_name = 'productA' and p.manufacturers_id = m.id
I believe this is what you're looking for
SELECT manufacturers.manufacturers_name
FROM products
JOIN manufacturers on manufacturers_id=products.manufacturers_id
WHERE manufacturers_name='product a'
With a join, you just need to follow this syntax, and remember that you have to set the matching columns equal to each other so you don't end up with invalid rows.
I'd show you how the equivalent of this using table joins, but I really don't want to encourage the use of that syntax, even by accident.

MySql Multiple Tables query

I wonder if any can help me understand something I'm trying to solve.
I'm working on a wordpress site but this is more a sql question as I'm just querying to get some results within a template file.
I have a gallery of pictures which are advert boxes, and I need to pull these in relation to a supplied movie name, to do this Im using some custom fields on the ad pic called 'adlink' (link off ad) and ad
I'm using the nextgen gallery plugin and querying those tables, and I have three tables in total that contain the data I need to query.
ngg_pictures, nggcf_field_values & nggcf_fields.
the nggcf tables are custom fields tables,
I have got so far I can get what I need in two seperate queries, but I can't combine these into one query as it means querying the nggcf_field_values table twice, which I can't seem to sort.
I have hardcoded the search criteria in for the mo, but the 'close-encounters' bit would be a passed var, and the '156' would be the pid from the first query.
SELECT `eg_ngg_pictures`.`filename`, `eg_nggcf_field_values`.`fid`, `eg_nggcf_field_values`.`pid`
FROM eg_ngg_pictures, eg_nggcf_field_values
WHERE ((`eg_nggcf_field_values`.`field_value` LIKE 'close-encounters') AND (`eg_nggcf_field_values`.`pid` = eg_ngg_pictures.pid))
SELECT `eg_nggcf_field_values`.`field_value`
FROM eg_nggcf_field_values, eg_nggcf_fields
WHERE ((`eg_nggcf_fields`.`field_name` = 'adlink') AND (`eg_nggcf_fields`.`id` = eg_nggcf_field_values.fid) AND (`eg_nggcf_field_values`.`pid` = '156'))
any help would be greatly appreciated, I can get the results with what I have, but I like to understand how to combine these two and write better SQl. Thanks MRO
After looking at the Wordpress extension, I think the eg_nggcf_fields is the table that contains the name for a custom field. The eg_nggcf_field_values table contains the values of that custom field per picture.
So if you're looking for two fields called moviename and adlink, you have to look up two rows in the field_values table. You can join a table twice if you give it a different alias:
select pic.filename
, pic.pid
, fv1.field_value as MovieName
, fv2.field_value as Adlink
from eg_ngg_pictures pic
inner join -- Find ID for the field called 'moviename'
eg_nggcf_fields f1
on f1.field_name = 'moviename'
inner join -- Find value for field moviename for this picture
eg_nggcf_field_values as fv1
on fv1.pid = pic.pid
and fv1.fid = f1.fid
inner join -- Find ID for the field called 'adlink'
eg_nggcf_fields f2
on f2.field_name = 'adlink'
inner join -- Find value for field adlink for this picture
eg_nggcf_field_values as fv2
on fv2.pid = pic.pid
and fv2.fid = f2.fid
where fv1.field_value like 'close-encounters'
First of all, I'd recommend sticking to modern ANSI syntax for JOINing tables, which means using the JOIN clause.
Instead of using:
FROM table1, table2 WHERE table1.id = table2.pid
use:
FROM Table 1 JOIN table2 ON table1.id = table2.id
For simplicity's sake, I'd also recommend you to alias tables, as that tends to make the code more readable. Instead of having to write out egg_ngg_pictures every time, you can simply refer to the alias you assign it instead.
Lastly, when you use a LIKE operator, you usually add a wild-card character (typically %. I.e. LIKE '%123' or LIKE '123%'). You seem to look only for complete matches, which means you can just stick to using =, as that should give you slightly better performance.
Now to rewrite your query, I'd use something like the following:
SELECT
pic.filename
, fieldval.fid
, fieldval.pid
, fieldval.field_value
FROM
eg_ngg_pictures pic
JOIN eg_nggcf_field_values fieldval ON fieldval.pid = pic.pid
JOIN eg_nggcf_fields fields ON fields.id = fieldval.fid
WHERE
((fieldval.field_value = 'close-encounters')
AND fields.field_name = 'ad_link'
Note that I am not able to test the query, as I do not have your schema. But by incorporating the two queries into a single query, the join on the field_Values.PID retreieved with the 'close_encounters' value should already exist.
If the query does not work, feel free to create a SQL fiddle with the relevant tables and some data, and I'll try and get it to work with that.