I'm using MySQL as a database and I have some design questions:
I have a table "locations" containing locID, lat & long & name values of a certain location.
I also have a table categories with ID and category-name & locID.
Now I want to make sure that categories can be assigned to multiple locations. How do I do that correctly? It doesn't make too much sense to have the same category stored multiple times, once for every locID, does it? What's the way to go here?
Thank you!
Ron
You can use a join table to model the many-to-many relationship.
location_category
location_id category_id
1 1
1 2
2 1
2 3
3 4
Add foreign key constraints to prevent invalid values from being entered into the table:
From location_category.location_id to locations.locID
From location_category.category_id to categories.ID
Also make (location_id, category_id) the primary key for the table to prevent adding a category to the same location multiple times.
When reading the data from the table, use JOINs to get the related data from the main tables:
SELECT ...
FROM location_category
JOIN locations ON location_category.location_id = locations.locID
JOIN categories ON location_category.category_id = categories.ID
WHERE ....
Related
I'm working on a mysql database select and cannot find a solution for this tricky problem.
There's one table "words" with id and names of objects (in this case possible objects in a picture).
words
ID object
house
tree
car
…
In the other table "pictures" all the information to a picture is saved. Besides to information to resolution, etc. there are especially informations on the objects in the picture. They are saved in the column objects by the ids from the table words like 1,5,122,345, etc.
Also the table pictures has a column "location", where the id of the place is written, where I took the picture.
pictures
location objectsinpicture ...
1 - 1,2,3,4
2 - 1,5,122,34
1 - 50,122,345
1 - 91,35,122,345
2 - 1,14,32
1 - 1,5,122,345
To tag new pictures of a particular place I want to become suggestions of already saved information. So I can create buttons in php to update the database instead of using a dropdown with multiple select.
What I have tried so far is the following:
SELECT words.id, words.object
FROM words, pictures
WHERE location = 2 AND FIND_IN_SET(words.id, pictures.objectsinpicture)
GROUP BY words.id
ORDER BY words.id
This nearly shows the expected values. But some information is missing. It doesn't show all the possible objects and I cannot find any reason for this.
What I want is for example all ids fo location 2 joined to the table words and to group double entries of objectsinpicture:
1,5,122,34
1,14,32
1,5,14,32,34,122
house
...
...
...
...
...
Maybe I need to use group_concat with comma separator. But this doesn't work, either. The problem seems to be where condition with the location.
I hope that anyone has an idea of solving this request.
Thanks in advance for any support!!!
This is a classic problem of denormalization causing problems.
What you need to do is store each object/picture association separately, in another table:
create table objectsinpicture (
picture_id int,
object_id int,
primary key (picture_id, object_id)
);
Instead of storing a comma-separated list, you would store one association per row in this table. It will grow to a large number of rows of course, but each row is just a pair of id's so the total size won't be too great.
Then you can query:
SELECT w.id, w.object
FROM pictures AS p
JOIN objectsinpicture AS o ON o.picture_id = p.id
JOIN words AS w ON o.object_id = w.id
WHERE p.location = 2;
i have a bit of a problem, i have two MySQL tables namely products and categories. The categories table has an id as the primary key and name of the category. The category id is a foreign key in the products table. I want to create a view, but i don't want the view to contain the id as the category,instead i want the category name to be shown in the view. I have tried every kind of JOIN but I'm still not getting the required result. What am i doing wrong? here is my latest join. Which is pretty much the closest to what i want.
SELECT c.title as title,ct.name as category, c.picture as picture
FROM companies c left join categories ct on ct.id=c.category
I have successfully gotten the title and picture, but the category remains null.
Thanks for the replies.. Michael turns out that you were right , I mixed up the tables when performing the insert via my web interface so there wasn't a match. Thanks a lot!
I did a database for my eCommerce using MySQL Workbench and I'm using Netbeans to put everything together. I have few tables that serve the purpose of what I'm trying to achieve. Two of these tables that are connected together are product and of course category.
I'm at the point of adding data into both tables. Each category has its own category_id obviously.
The issue: one single product can be in multiple categories (therefor have multiple category_id but I don't know how to do that because Netbeans only seem to allow one category_id per product whether I use a command line or do it manually.
As you can see on the pictures, the product named mac is set to technology for home which category_id is 208. But the same product could also be part of 209 (technology for office).
How do I go about achieving that? Do I need to enter a new row for the same product every time I need a product to be part of multiple categories? Let's say if a product can be part of 3 categories, do I need to enter 3 records? Is there another way of doing so because to the knowledge I have, that would be very long and exhausting, no?
Thanks
This is called a many-to-many relationship in the entity-relationship lingo. A product can have multiple categories, and a category can have multiple products.
To do this in a relational database, you need three tables.
product: product_id, name, description, etc
category: category_id, catname, catdescription, etc
And then this so-called join table to establish the relationships between products and categories.
product_category: product_id, category_id
The primary key of product_category is both columns together -- it's a compound primary key.
If you have these products
1 chromebook
2 minitower
3 macbook
4 laptop
and these categories
1 chromeos
2 portable
3 windows 7
4 macos
You then will have these entries in your product_category table
1 1 chromebook categories: ... chromeos
1 2 ... portable
2 3 minitower category ... windows 7
3 2 macbook categories ... portable
3 4 ... macos
4 2 laptop categories ... portable
4 3 ... windows 7
So, if you want to see the categories for each product, you can do
SELECT name, description,
GROUP_CONCAT(catname) categories
FROM product
JOIN product_category USING (product_id)
JOIN category USING (category_id)
Likewise, if you want all the laptops you can do this.
SELECT name, description
FROM product
JOIN product_category USING (product_id)
JOIN category USING (category_id)
WHERE catname = 'laptop'
If you want all the macos laptop devices, it's a little more complex.
SELECT name, description
FROM product p
JOIN product_category pca ON p.product_id = pca.product_id
JOIN category ca ON pca.product_id = ca.product_id
AND ca.catname = 'macos'
JOIN product_category pcb ON p.product_id = pcb.product_id
JOIN category ca ON pcb.product_id = cb.product_id
AND cb.catname = 'laptop'
Notice that the composite primary key prevents you from assigning a product more than once to a category and vice versa.
Pro tip: For clarity it's a good idea to use the same column name in all your tables for the values on which you join. For example, the product_id shows up in both the product and product_category table.
You can use another table to achieve this. Name it something like categories_products. It should have three columns
id
category_id
product_id
Then have entries for each category a product is in, like:
id=1,
category_id=208,
product_id=1
and
id=2,
category_id=209,
product_id=1
You'll want to research the Many to Many Data Model
In theory you could create a table for products, a table for categories, and a table to link the two. This would allow for a virtually infinite number of categories that a single product could be linked to.
Using table structure you have it is not possible.
The best option is storing comma-separated string in category_field and handle it in your application making one more query
The second option is creation of new table with two columns group_categoy_id and category_id and use group_category_id in your product table instead of category_id. In this case you can have endless group of categories, and you need only one query to get all data you need.
I have question related to mysql relationships. Let's say I have 4 table companya companyb companyc and companyd, each containing 3 columns: name, phone, and age. Also I have another table called address which I want to link to each companyX with this address table , let’s say if I did select * from companyX; the address column should appearnext to each name.
Can this be done with mysql?
First of all, if the company tables have the exact same structure why don't you use only a single table to store the information? You may want to read about database normalization.
Secondly you could create a relation table named something like 'companiesAddresses' and store fields such as "CompanyID" and "AddressID" in it (you obviously would have to create a primary key column in your companyX's table and do the same in the 'addresses' table so then you could use the INNER JOIN clause to get the information you want such as SELECT companyX.companyName, addresses.Address FROM companyX INNER JOIN companiesAddresses ON companyX.CompanyID = companiesAddresses.CompanyID INNER JOIN addresses ON companiesAddresses.AddressID = addresses.AddressID.
I hope I understood what you want correctly.
I currently have 3 tables,
Users (Id, PositionId)
MonsterInstances (Id, PositionId)
TreasureInstances (Id, PositionId)
and 1 position table.
Positions (Id, Coordinate, TypeId)
PositionId, in my 3 tables, are foreign keys into my Position table.
I want to use a single Positions table, as shown above, to normalize all of my position data. The problem I am facing is that I must identify a type so that when my query executes, it knows which table to query.
e.g.
SP -- GetObjectByPosition (positionId)
IF TypeId = 1
SELECT * FROM Users JOIN... WHERE PositionId = positionId
ELSE IF TypeId = 2
SELECT * FROM MonsterInstances JOIN...
This seems like bad design to me. The only way around it I can percieve would be to have 3 seperate tables.
UserPositions
MonsterInstancePositions
TreasureInstancePositions
However, I'm not always interested in extracting user, monster, or treasure data. Sometimes I only want the position Id and location -- which would mean with three tables, I would have to do a union.
Is there a better way to do this?
Users, MonsterInstances, TreasureInstances could be rewritten as a single "ObjectInstances" table that includes a type column. Then queries that would work against those 3 tables separately would instead work against ObjectInstances and a typeID, referencing a new OjbectTypes table. Make sense?