How can i convert a comma separated columns into junction table? - mysql

I am pretty new to mysql and this site. I got an old mysql database (100.000 entries) to migrate to our new system. This is the old table:
CUSTOMER
Customer_ID Name Categories
1 Bob 1,2
2 Phil NULL
3 Ines 10,8
4 Carol 1
5 Rick 13,2
And i need the following structure:
CUSTOMER
Customer_ID Name
1 Bob
2 Phil
3 Ines
4 Carol
5 Rick
Category
Category_ID Category_Name
1 Biker
2 Doctors
3 Teacher
... ...
13 Drivers
CustomerHasCategory
Customer_ID Category_ID
1 1
1 2
3 10
3 8
4 1
5 13
5 2
Thanks for any help.

I also had this problem but not in MySQL. I solved it with Python using the Pandas library. So, the exact steps I followed won't be useful for you. However, I'll show you the general idea behind the solution I used.
Below is image of the original column
First, I splitted the text into columns using the comas as the delimiter.
Next, I 'stacked' the columns
Finally, I removed the artefact column(s). So, I have only the ID and the values columns. This creates a one-to-many relationship.

Related

Duplicate or unpredictable results in MySQL

I'm trying to join a few tables in MySQL. Our setup is a little unique so I try to explain as good as I can.
I have a table 'INVENTORY' that represents the current items on stock.
These items are stored in a table 'COMPONENT'
Components are being used in installations.
Every user can have multiple installations and the same component can be used in multiple installation as well.
To uniquely map a component to an installation, it can be assigned to a PRODUCT. a product as has a 1-1 relationship with an installation. A component is not directly related to an installation
To finally assign a product to a specific installation a mapping table COMPOMENT_PRODUCT is used.
Example:
A component is like a part, lets say a screw. This screw is used in a computer. The very same screw can be used on multiple computers. But each computer can only be used on one specific installation.
TABLE COMPOMENT_PRODUCT
COMPOMENT_ID PRODUCT_ID
1 1
1 2
2 1
2 2
So we have the components C1 and C2 relevant for two installations.
TABLE INVENTORY
COMPOMENT_ID INSTALLATION_ID ON_STOCK
1 1 5
1 2 2
What I want to achieve
Now, I want to retrieve the inventory state for all components. But, not every component has an inventory record. In these cases, the ON_STOCK value from the inventory shall be NULL
That means, for this example I'd expect the following results
COMPOMENT_ID PRODUCT_ID ON_STOCK
1 1 5
1 2 2
2 1 NULL
2 2 NULL
But executing this query:
SELECT DISTINCT
COMPONENT_PRODUCT.COMPONENT_ID,
COMPONENT_PRODUCT.PRODUCT_ID,
INVENTORY.ON_STOCK
FROM INVENTORY
RIGHT JOIN COMPONENT_PRODUCT ON COMPONENT_PRODUCT.COMPONENT_ID =
INVENTORY.COMPONENT_ID
returns the following resultset:
COMPONENT_ID PRODUCT_ID ON_STOCK
1 1 5
1 2 5
1 1 2
1 2 2
2 1 (null)
2 2 (null)
Now, my next thought was, "of course, this is how joins behave, okay I need to group the results". But the way SQL works, the aggregation is not entirely predictable. SO when I
GROUP BY COMPONENT_PRODUCT.COMPONENT_ID,COMPONENT_PRODUCT.PRODUCT_ID
I get this result:
COMPONENT_ID PRODUCT_ID ON_STOCK
1 1 5
1 2 5
2 1 (null)
2 2 (null)
I have prepared a Fiddle here: http://sqlfiddle.com/#!9/71ca87
What am I forgetting here? Thanks in advance for any pointers.
Try this query -
SELECT DISTINCT
COMPONENT_PRODUCT.COMPONENT_ID,
COMPONENT_PRODUCT.PRODUCT_ID,
INVENTORY.ON_STOCK
FROM INVENTORY
RIGHT JOIN COMPONENT_PRODUCT ON COMPONENT_PRODUCT.COMPONENT_ID =
INVENTORY.COMPONENT_ID
AND COMPONENT_PRODUCT.PRODUCT_ID = INVENTORY.INSTALLATION_ID

Edit product selling location using mysql

I'm building a e-Commerce platform (PHP + MySQL) and I want to add a attribute (feature) to products, the ability to specify (enable/disable) the selling status for specific city.
Here are simplified tables:
cities
id name
==========
1 Roma
2 Berlin
3 Paris
4 London
products
id name cities
==================
1 TV 1,2,4
2 Phone 1,3,4
3 Book 1,2,3,4
4 Guitar 3
In this simple example is easy to query (using FIND_IN_SET or LIKE) to check the availability of product for specific city.
This is OK for 4 city in this example or even 100 cities but will be practical for a large number of cities and for very large number of products?
For better "performance" or better database design should I add another table to table to JOIN in query (productid, cityid, status) ?
availability
id productid cityid status
=============================
1 1 1 1
2 1 2 1
3 1 4 1
4 2 1 1
5 2 3 1
6 2 4 1
7 3 1 1
8 3 2 1
9 3 3 1
10 3 4 1
11 4 3 1
For better "performance" or better database design should I add
another table
YES definitely you should create another table to hold that information likewise you posted rather storing in , separated list which is against Normalization concept. Also, there is no way you can gain better performance when you try to JOIN and find out the details pf products available in which cities.
At any point in time if you want to get back a comma separated list like 1,2,4 of values then you can do a GROUP BY productid and use GROUP_CONCAT(cityid) to get the same.

mySQL - foreign key to multiple tables? [duplicate]

This question already has answers here:
Possible to do a MySQL foreign key to one of two possible tables?
(6 answers)
Closed 8 years ago.
I am fumbling my way through phpMyAdmin and mySQL. I’m creating something where a customer can register multiple products. The data coming in is:
Category > Type > Size > Color
So for example:
Cookware > Oven > 5 qt > Blue
Bakeware > Casserole > 3qt > Blue
Accessories > Textiles > N/A > Blue
Etc.
I have set up one table with categories, and 4 tables to cover each product type.
Categories
ID Category
1 Cookware
2 Bakeware
3 Accessories
4 Serveware
Cookware Table
ID Type
1 Oven
2 Skillet
3 Roaster
Bakeware Table
ID Type
1 Casserole
2 Pie Dish
3 Baker
Etc.
Then, in the registration table, I set up a foreign key to link the category to the category table. So it would look something like this:
ID CustID Category Type Size Color
1 20 2 1 11 34
1 20 1 1 9 34
(sorry the formatting is so terrible! not sure how to fix)
But, I’m stuck on how to link the product type to the correct product type table since it is dependent on which category they picked. Hopefully this makes sense. Maybe I don't even need to link them and can still request the data somehow through a query?
Merge the last 2 tables ?
ID Type Category
1 Oven 1
2 Skillet 1
3 Roaster 1
4 Casserole 2
5 Pie Dish 2
6 Baker 2

MYSQL - Add multiple users to a table column

Maybe it's because I don't understand how to search for the right verbiage, but I'm having difficulty understanding how to attach multiple users to a table with multiple columns.
Here is what I'm attempting to do:
table name: user
user_id user_name
1 abc
2 xyz
3 pqr
4 new
table2 name : brackets
id user_id bracket_name
1 4,2 bracket_1
2 4,3,1 bracket_2
3 2,1 bracket_3
4 3,4,2 bracket_4
-- OR --
table name: user
user_id user_name brackets_id
1 abc 2,3
2 xyz 1,3,4
3 pqr 2,4
4 new 1,2,4
table2 name : brackets
brackets_id user_id bracket_name
1 4,2 bracket_1
2 4,3,1 bracket_2
3 2,1 bracket_3
4 3,4,2 bracket_4
I'm using nodejs and sequalize as my ORM and understand enough to read, write, delete and update to these tables, but when it comes to organizing my data, I'm completely lost!
Is it possible to add an array to MYSQL with the user ID's or the brackets that the user is allowed to access? The bracket are generated by a user and then they can invite their friends to join a bracket. Users can join multiple brackets and join other brackets as users.
Any guidance would be very helpful!
I think a Junction Table would simplify this for you: http://en.wikipedia.org/wiki/Junction_table
It would look something like:
table name: user
user_id user_name
1 abc
2 xyz
3 pqr
4 new
table2 name : brackets
brackets_id bracket_name
1 bracket_1
2 bracket_2
3 bracket_3
4 bracket_4
table3 your junction table:
user_id brackets_id
1 2
1 3
2 1
2 3
2 4
etc.etc.

Storing data in a link table

Supoose I have the following:
tbl_options
===========
id name
1 experience
2 languages
3 hourly_rate
tbl_option_attributes
=====================
id option_id name value
1 1 beginner 1
2 1 advanced 2
3 2 english 1
4 2 french 2
5 2 spanish 3
6 3 £10 p/h 10
7 3 £20 p/h 20
tbl_user_options
================
user_id option_id value
1 1 2
1 2 1
1 2 2
1 2 3
1 3 20
In the above example tbl_user_options stores option data for the user. We can store multiple entries for some options.
Now I wish to extend this, i.e. for "languages" I want the user to be able to specify their proficiency in a language (basic/intermediate/advanced). There will also be other fields that will have extended attributes.
So my question is, can these extended attributes be stored in the same table (tbl_user_options) or do I need to create more tables? Obviously if I put in a field "language_proficiency" it won't apply to the other fields. But this way I only have one user options table to manage. What do you think?
EDIT: This is what I propose
tbl_user_options
================
user_id option_id value lang_prof
1 1 2 null
1 2 1 2
1 2 2 3
1 2 3 3
1 3 20 null
My gut instinct would be to split the User/Language/Proficiency relationship out into its own tables. Even if you kept it in the same table with your other options, you'd need to write special code to handle the language case, so you might as well use a new table structure.
Unless your data model is in constant flux, I would rather have tbl_languages and tabl_user_languages tables to store those types of data:
tbl_languages
================
lang_id name
1 English
2 French
3 Spanish
tbl_user_languages
================
user_id lang_id proficiency hourly_rate
1 1 1 20
1 2 2 10
2 2 1 15
2 2 3 20
3 3 2 10
Designing a system that is "too generic" is a Turing tarpit trap for a relational SQL database. A document-based database is better suited to arbitrary key-value stores.
Excepting certain optimisations, your database model should match your domain model as closely as possible to minimise the object-relational impedance mismatch.
This design lets you display a sensible table of user language proficiencies and hourly rates with only two inner joins:
SELECT
ul.user_id,
u.name,
l.name,
ul.proficiency,
ul.hourly_rate
FROM tbl_user_languages ul
INNER JOIN tbl_languages l
ON l.lang_id = ul.lang_id
INNER JOIN tbl_users u
ON u.user_id = ul.user_id
ORDER BY
l.name, u.hour
Optionally you can split out a list of language proficiencies into a tbl_profiencies table, where 1 == Beginner, 2 == Advanced, 3 == Expert and join it onto tbl_user_languages.
i'm thinking it's a mistake to put "languages" as an option. while reading your text it seems to me that english is an option, and it might have an attribute from option_attributes.