I'm trying to advance my knowledge of mysql from "I can make it work" to "I can make it work correctly". I'm working with joins right now and I was wondering the best way of doing the following:
I have 2 tables "items" and "categories". Inside the "items" table I have a field called category which will be linked to the "categories" table primary key cid. What is the best way of doing this? This is how I've always done it but I feel it's not the best way by any means
SELECT C.something, C.soemthing 2 FROM categories C, items I WHERE C.cid=I.category AND C.categoryName='New'
Your query is already correct but I'll recommend to use ANSI SQL-92 format
SELECT C.something, C.soemthing2
FROM categories C INNER JOIN items I
on C.cid=I.category
WHERE C.categoryName='New'
question, what are you trying to achieve?
Your query would return the correct result set, however the following is more readable:
SELECT C.something, C.soemthing 2
FROM categories C
INNER JOIN items I ON C.cid = I.category
WHERE C.categoryName='New';
Related
I have a table called "customers". It contains a column called "id" and for some amazing reason, I am getting the error:
#1054 - Unknown column 'c.id' in 'on clause'
When I do this join:
SELECT c.co_name, p.name
FROM `customers` as c, `products` as p, `customer_product` as cp
Join `products`
On c.id = cp.customer_id
I have also tried removing the alias and writing out customers.id and I still get the error.
Why am I getting the error - what have I done wrong ?
Many Thanks !
It is probably failing as you are using alias and full table.. pick one... Also, you will get a Cartesian result as you don't have anything tying between cp and p tables.. POSSIBLE solution.
SELECT
c.co_name,
p.name
FROM
customers c
JOIN customer_product cp
on c.id = cp.customer_id
Join products p
on cp.product_id = p.id
Clarification per request.
I have a style I like to use for doing my SQL-based queries. If you click on my image of the answer (or anyone for that matter), it will take you to their profile / history. Then if you click on the MySQL tag, it will take you to a list of all answers I've provided for MySQL (or whatever tag you are interested in from me or any other user). From that, look at the pattern of styling of my answers.
I like to use indentation as a visual representation of how table "A" correlates to "B" and from "B" to "C" as can be seen here. You used a cross between comma separated tables with no defined JOIN and then a join only on the third table. This means only the JOIN condition was applied.
When I did the query, I listed the primary table first, JOIN to the second and immediately identify the ON condition between the FIRST (left-side) table and the SECOND (right-side) table. Since you have a link-table (identifying customers and products), the first criteria joined from the customer table to the link table by the customer. So now, you need to get from the link table to the product table. So now, the indentation moves the product table further in and now the FIRST (left-side) table is the LINK (customer_products) table joined to the SECOND (right-side) table of products. Now the ON condition between those.
So now, relations are established between A-B and B-C.
Once this is done, then you can get whatever columns to be returned and THEN apply any other criteria / group by / order by conditions. Note, If I had additional criteria at one of the secondary (or deeper) levels, I would add the criteria exactly at that location. This way, when dealing with left-join conditions, I am not accidentally turning it to an INNER join by putting the criteria in the WHERE clause.
Hope this and some other answers that you can look at help in your future querying.
This is really a two-part question, but in order not to mix things up, I'll divide into two actual questions. This one is about creating the correct SQL statement for selecting a row based on values in a many-to-many related table:
Now, the question is: what is the absolute simplest way of getting all resources where e.g metadata.category = subject AND where that category's corresponding metadata.value ='introduction'?
I'm sure this could be done in a lot of different ways, but I'm a novice in SQL, so please provide the simplest way possible... (If you could describe briefly what the statement means in plain English that would be great too. I have looked at introductions to SQL, but none of those I have found (for beginners) go into these many-to-many selections.)
The easiest way is to use the EXISTS clause. I'm more familiar with MSSQL but this should be close
SELECT *
FROM resources r
WHERE EXISTS (
SELECT *
FROM metadata_resources mr
INNER JOIN metadata m ON (mr.metadata_id = m.id)
WHERE mr.resource_id = r.id AND m.category = 'subject' AND m.value = 'introduction'
)
Translated into english it's 'return me all records where this subquery returns one or more rows, without returning the data for those rows'. This sub query is correlated to the outer query by the predicate mr.resource_id = r.id which uses the outer row as the predicate value.
I'm sure you can google around for more examples of the EXIST statement
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.
I have concluded that my first quick fix of storing an array of ids in a singular database field (1,5,48) is probably not best but if I break them out into a joining table of 'parent item id' (singular) and then sub related item id (multiple) which links to a separate table it would be better.
But now I am unsure what mysql query to use to get matches.
So a search form is submitted where "related_item" array is "1,5,8" and one of my "parent_items" has related item matches of "1" and "8" in the joining table....
So what mysql query would return these matches?
UPDATE:
I have one table 'companies' maybe HSBC and TOPSHOP as example records.
There is a separate table of 'industries' maybe 'banking' and 'retail'
There is a joining table which is company_id and industry_id which pairs them both together
So if someone submits a search form for where industry = 'banking' or 'retail' how would I return the company records for 'topshop' and 'hsbc'
Something like this... its unclear to me form you description if you are "searching" children or parents. I think you mean to search children so:
-- SEARCH CHILDREN --
SELECT p.*, c.* FROM child_table c
LEFT JOIN linking_table l ON (p.id = l.child_table_id)
LEFT JOIN parent_table p ON (l.parent_item_id = p.id)
WHERE c.id IN (1,5,4,8)
-- OPTIONAL AND CLAUSE for p.id = ? --
If you mean to search parents then you can just rework the order, although you could use the exact same query with the exception that your WHERE IN clause would be on p.id instead of c.id.
Be aware though that this will get you 1 row per match for the children so you will have the same parent multiple times. If you dont need the actual child data then you could use DISTINCT to only return one instance.
There are 4 sql tables:
Listings(Amount, GroupKey, Key, MemberKey),
Loans(Amount, GroupKey, Key, ListingKey),
Members(City, GroupKey, Key)
Groups(GroupRank, Key, MemberKey)
Now, if one wants to find out the loans which are also listings and find the members city and GroupRank for the members in the loan table. Here, the group table contains information about grous of which members are a part of.
and also perform a select operation as given below:
select Listings.Amount, Members.City, Groups.GroupRank
from listings, loans, members, groups
where Listings.Key=Loans.ListingKey and
Members.Key=Listings.MemberKey and
Listings.GroupKey=Groups.Key
The above join is giving an incorrect result, please point out where I am going wrong.
Also I am new to SQL so please excuse the novice question.
Note: The following is just a guess what your problem is. Like others said, clearify your question.
You want to JOIN
( http://dev.mysql.com/doc/refman/5.1/de/join.html )
those tables. What you write is just another form of a join, meaning it has the same effect. But you "joined" a bit too much. To make things clearer a syntax has been invented to make things clearer and avoid such mistakes. Read more about it in the link given above.
What you want to achieve can be done like this:
SELECT
Listings.Amount, Members.City, Groups.GroupRank
FROM
Listings
INNER JOIN Groups ON Listings.GroupKey=Groups.Key
INNER JOIN Members ON Members.Key=Listings.MemberKey
You don't do a SELECT on the Loans table, you don't need it in this query.
This is the INNER JOIN which will give you a result where every row in table A has an according entry in table B. When this is not the case, you have to use the LEFT or RIGHT JOIN.
Maybe the problem is related to the join type (INNER). Try LEFT JOIN for example but Mark has right: you should clearify your question.
I would firstly change your query to use the more modern join syntax, which allows outer joins. Tr this:
select Listings.Amount, Members.City, Groups.GroupRank
from listings
left join loans on Listings.Key=Loans.ListingKey
left join members on Members.Key=Listings.MemberKey
left join groups on Listings.GroupKey=Groups.Key
and/or Loans.GroupKey=Groups.Key
and/or Members.Key=Groups.MemberKey
You may need to play with the criteria on the last join (maybe they should be "or" not "and" etc).