Adding data to table by comparing one table to another - mysql

I am working to split apart this one large table into smaller tables for easier management via foreign keys, and have come across a dilemma with trying to bring the data back together. I am new to working with this type of data merging so I am a bit lost.
There are 3 tables: one table with a list of product owners, one table with a list of systems they are responsible for, and the original table with all of the data (examples below):
Product Owners Table:
+----+---------------+
| id | product_owner |
+----+---------------+
| 1 | User1 |
+----+---------------+
PRIMARY KEY: id
System Table:
+----+-----------+---------------+
| id | system | product_owner |
+----+-----------+---------------+
| 6 | Server1 | NULL |
+----+-----------+---------------+
FOREIGN KEY: product_owner(id)
Original Table:
+---------+---------------+
| system | product_owner |
+---------+---------------+
| Server1 | User1 |
+---------+---------------+
I want to take the data from the original table and merge it with the new system table, however I don't want to go the route of multiple UPDATE statements to add what needs to be added. What's the best route to approach on this?

After a bunch more poking around and reading additional terminology, I was able to solve my problem by using a mix of join statements in conjunction with update, set and where statements:
update system_table a
join original_table.system b
on a.system = b.system
join product_owner c
on c.product_owner = b.product_owner
set a.product_owner = c.id
where c.product_owner = b.product_owner;

Related

Over 2500 tables in mysql

My application stores login information of over 2500 employees in a table named "emp_login".
Now I have to store the activities of every employee on daily basis. For this purpose i have created a separate table for every employee. E.g. emp00001, emp0002... Each table will have about 50 columns.
After digging in alot on stackoverflow I'm kind of confused. Many of the experts say that database having more than 200-300 tables on mysql is considered to be poorly designed.
My question is whether it is good idea to have such a bulk of tables? Is my database poorly designed? Should i choose other database like mssql? Or some alternative idea is there to handle the database of such applications??
Do -not- do it that way. Every employee should be in 1 table and have a primary key index ID ie:
1: Tom
2: Pete
You then assign the actions with a column that references the employees ID number
Action, EmployeeID
You should always group identical entities in a table with index ids and then link properties / actions to those entities by Id. Imagine what you would have to do to search a database that consisted of a different table for every employee. Would defeat the whole point of using SQL.
Event table could look like:
Punchin, 1, 2018/01/01 00:00
That would tell you Tom punched In at 2018/01/01 00:00. This is a very simple example, and you prob wouldn’t wanna structure an event table that way but it should get you on the right track.
This is nothing to do with MySQL but to do with your design which is flawed. You should have one table for all your employees. This contains information unique to the employees such as firstname, lastname and email address.
|ID | "John" | "Smith" | "john.smith#gmail.com" |
|1 | "James" | "Smith" | "james.smith#gmail.com" |
|2 | "jane" | "Jones" | "jane.jones.smith#yahoo.com" |
|3 | "Joanne" | "DiMaggio" | "jdimaggio#outlook.com" |
Note the ID column. Typicially this would be an integer with AUTO_INCREMENT set and you would make it the Primary Key. Then you get a new unique number every time you add a new user.
Now you have separate tables for every piece of RELATED data. E.g. the city they live in or their login time (which I'm guessing you want from the table name).
If it's a one to many relationship (i.e. each user has many login times), you create a single extra table which REFERENCES your first table. This is a DEPENDENT table. Like so:
| UserId | LoginTime |
| 1 | "10:00:04 13-09-2018" |
| 2 | "11:00:00 13-09-2018" |
| 3 | "11:29:07 14-09-2018" |
| 1 | "09:00:00 15-09-2018" |
| 2 | "10:00:00 15-09-2018" |
Now when you query your database you do a JOIN on the UserId field to connect the two tables. If it were only their LAST login time, then you could put it in the user table because it would be a single piece of data. But because they will have many login times, then login times needs to be its own table.
(N.b. I haven't put an ID column on this table but it's a good idea.)
If it's data that ISN'T unique to the each user, i.e. it's a MANY to MANY relationship, such as the city they live in, then you need two tables. One contains the cities and the other is an INTERMEDIARY table that joins the two. So as follows:
(city table)
| ID | City |
| 1 | "London" |
| 2 | "Paris" |
| 3 | "New York" |
(city-user table)
| UserID | CityID |
| 1 | 1 |
| 2 | 1 |
| 3 | 3 |
Then you would do two JOINS to connect all three tables and get which city each employee lived in. Again, I haven't added an ID field and PRIMARY KEY to the intermediary table because it isn't strictly necessary (you could create a unique composite key which is a different discussion) but it would be a good idea.
That's the basic thing you need to know. Always divide your data up by function. Do NOT divide it up by the data itself (i.e. table per user). The thing you want to look up right now is called "Database Normalization". Stick that into a search engine and read a good overview. It wont take long and will help you enormously.

MySQL link two tables together implicitly

Suppose we have two tables
A table called people with people linked to a bank account balances
| id | name | account_id |
--------------------------
| 1 | bob | 11 |
--------------------------
| 2 | sam | 22
A table called accounts with bank account balances
| id | value |
--------------
| 11 | 200 |
--------------
| 22 | 500 |
In order to link the two tables you can do
SELECT a.value as account_balance
FROM people p
WHERE p.name="bob"
LEFT JOIN accounts a ON p.account_id = a.id`
This would return
id => 1
name => bob
account_balance => 200
That's cool - but I am wondering if there is a more implicit way to do this via SQL linkage (foreign keys or otherwise). Can we in MySQL add links in some other way so that when we do a SELECT, it already knows to return value instead of **account_id **?
I'm asking this because I am creating a system where my users can create lookup tables and link them to other tables - but it must be do-able without any programming. The only other way I can think of is to set the name of account_id for example to accounts.value and treat that as a foreign key when doing a SELECT.
I would have to get the column structure and analyze and then determine that there is a foreign key and then return the appropriate foreign column by looking at the column name.

MySQL Moving table from varchar to int

I am moving an old Mantis table that had a varchar(64) category_id column to a new Mantis table that has a int(10) category_id column.
The simplified structure is as follows
bug_table (Old DB)
+----+-------------+-------------+--------+
| id | project_id | category_id | report |
+----+-------------+-------------+--------+
| 1 | 0 | Server | crash |
| 2 | 0 | Database | error |
| 3 | 1 | Server | bug |
| 4 | 1 | Server | crash |
+----+-------------+-------------+--------+
category_table (New DB)
+----+------------+----------+
| id | project_id | name |
+----+------------+----------+
| 0 | 1 | Server |
| 1 | 1 | Database |
| 2 | 2 | Server |
| 3 | 2 | Database |
+----+------------+----------+
I need a magical query that will replace category_id in the bug_table with the numerical category_id in the category_table. Thankfully I am able to match rows by project_id and categories by name.
Here is the query I am working on but have gotten stuck in the complexity
UPDATE bug_table b SET b.category_id = c.id USING category_table WHERE b.category_id = c.name
I like to approach such a task a little differently than you do for a new lookup/reference table.
To me, the new category table would only have id and name columns. There are only two rows based on the sample data: Server and Database. Yes, I realize there could be other names, but those can easily be added, and should be added, before proceeding to maximize the id matching that follows.
Next I would add a new column to the bug table that could be called 'category_new' with the data type that will store the new category id. Alternatively, you could rename the existing category_id column to category, and the new column for the id's could then be column_id.
After all that is done then you can update the new column by joining the category on names and set the id that matches: (note this assumes the non-alternative approach mentioned in step 2)
UPDATE bug_table JOIN category_table ON bug_table.category_id = category_table.name
SET bug_table.category_new = category_table.id
After that runs, check the new column to verify the updated id's.
Finally, after successful update, now the old category_id column (with the names) from the bugs_table can be dropped, and the category_new column can be renamed as the category_id.
=====
Note that if you decide to go with the alternative column approach mentioned, of course the query will be similar but differ slightly. Then only a column drop is needed at the end
If there are other tables to apply the same category changes, the operation (basically steps 2 through 5) would be similar for those tables too.

Dynamic value to display numbers of entries in second table

I've got multiple entries in table A and would like to display the number of entries in a coloumn of table B. Is there a way to create a dynamic cell-content displaying the number of entries in a table?
I'm a beginner in MySQL and did not find a way to do it so far.
Example table A:
+----+------+------------+
| id | name | birthday |
+----+------+------------+
| 1 | john | 1976-11-18 |
| 2 | bill | 1983-12-21 |
| 3 | abby | 1991-03-11 |
| 4 | lynn | 1969-08-02 |
| 5 | jake | 1989-07-29 |
+----+------+------------+
What I'd like in table B:
+----+------+----------+
| id | name | numusers |
| 1 | tblA | 5 |
+----+------+----------+
In my actual database there is no incrementing ID so just taking the last value would not work - if this would've been a solution.
If MySQL can't handle this the option would be to create some kind of cronjob on my server reading the number of rows and writing them into that cell. I know how to do this - just checking if there's another way.
I'm not looking for a command to run on the mysql-console. What I'm trying to figure out is if there's some option which dynamically changes the cell's value to what I've described above.
You can create a view that will give you this information. The SQL for this view is inspired by an answer to a similar question:
CREATE VIEW table_counts AS
SELECT table_name, table_rows
FROM information_schema.tables
WHERE table_schema = '{your_db}';
The view will have the cells you speak of. As you can see, it is just a filter on an already existing table, so you might consider that this table information_schema.tables is the answer to your question.
You can do that directly with COUNT() for example SELECT COUNT(*) FROM TblA The you get all rows from that table. If you IDXs are ok then its very fast. If you write it to another table you have to make an request too to get the result of the second table. So i think your can do it directly.
If you have some performance problems there are some other possibilities like Triggers or Stored Procedures to calculate that result and save them in a memory table to get a better performance.

MySQL Multiple references between tables

This question is probably quite easy to answer, but since I haven't got much experience in database design, I'm stuck. I don't even know how to google this because I don't know the terminology ....
I have a mysql database with two tables and in the first table i need to make MULTIPLE references to the second table. What should I use? Can I select multiple matches with Enum? Or should I just use a comma separated list and varchar?
|MAIN TABLE
|==========================================
| id (primary index)
| date (tstamp)
| product name (varchar)
| componentids (int, enum, varchar ???)
|===========================================
|COMPONENTS TABLE
|===========================================
| componentid (int)
| name (varchar)
| info (varchar)
|===========================================
so a possible scenario would be this:
|MAIN TABLE
|=====================================================
| id | 1 | 2 |
| date | 34958734958 | 349587123138 |
| product name | A test product | A second product |
| componentids | 2,3 | 1,2 |
|=====================================================
|COMPONENTS TABLE
|========================================================
| componentid | 1 | 2 | 3 |
| name | Component 1 | Component 2 | Component 1 |
| info | info. text | info. text | info. text |
|========================================================
how do I achieve this in an effective way?
thank you very much for your help!
What you're after is a many-to-many relationship. Each component can belong to multiple products, and each product can have multiple components. I'd strongly recommend using a third table for this, maybe called product_components.
Your main table has (id, date, name)
Your components table has (id, name, info)
Your product_components table has (product_id, component_id). Each of these is a foreign key that references the main table and component table respectively.
This maintains "referential integrity" which means that it becomes impossible to have a product referring to a component that doesn't exist (e.g. the database will throw an error if you try).
And yes, you can select the multiple components associated with one product in one go this way.
SELECT components.*
FROM components
JOIN product_components
ON components.id = product_components.component_id
WHERE product_components.product_id = <some product id>
No comma-separated lists or varchar. That's not the relational way.
How should it go? Are there many rows in the main table for every one in component, or visa versa?
A one-to-many relationship means adding a foreign key to the many table and JOINing the two:
select *
from main
join component
on main.componentid = component.componentid
This will match all the rows in the main table with their component counterpart.