how to create index table based on an existing table in Mysql - mysql

I have a table contains columns like:
time tv_program user_name
xxx friends John
xxx Game of Thrones Kate
...
...
Now I want to create separate index table for tv_program and user_name like:
id tv_program
1 friends
2 Game of Thrones
3 ...
4 ...
id user_name
1 John
2 Kate
3 ...
4 ...
and update the original table, replace the tv_program and user_name with the index number instead like
time tv_program user_name
xxx 1 1
xxx 2 2
... ... ...
Is there any simple way to do this? many thanks!!

You basically want to normalise your data, and you can do it with MySQL queries:
Create a table tv_programs table with id autoincrement, name index unique
INSERT INTO tv_programs (name) SELECT DISTINCT tv_program
FROM original_table
Now you have a table containing the programs, with their id automatically created by MySQL, so you now have to run an UPDATE with join (using string names, could be slow if you have lots of data and no index, but you just run it once) and update the original table with the id of the joined table (tv_programs)
UPDATE original_table ot LEFT JOIN tv_programs tp ON ot.tv_program = tp.name SET ot.tv_program = tp.id
And now you can change the type of tv_program column to INT
Repeat with the other table. Do backups before, or add a column to the original table (e.g. tv_program_id) and update that one with IDs, so that you can run other queries to check the results before dropping the old column and continue
Hope that's clear.

Related

How to do a "DELETE" relational database with another table in MySQL

I want to have a relational data between two table with DELETE query.
I don't know what keyword should I search and such confusing for me to learn relational database.
So in this case, I want to delete one of the user data in the user table.
So the buy_product table which contains the user_id column will also be deleted along with the rows in it.
This is user table:
user_id
name
1
John
2
Doe
This is buy_product table:
id_product
name
user_id
1
Cookies
2
2
Pizza
2
3
Burger
1
For example, if I run the DELETE FROM user WHERE user_id = 2 query, the result is:
user_id
name
1
John
And buy_product table with user_id = 2 also deleted the data that I want without run DELETE FROM buy_product WHERE user_id = 2 query like this:
id_product
name
user_id
3
Burger
1
I think for all understandable answers means a lot to me. Thanks!
If you defined a foreign key constraint with ON DELETE CASCADE between buy_product and user then deleting a row from the parent table user will automatically delete the related rows in the child table buy_product.
For example, buy_product could be created as:
create table buy_product (
id_product int,
name varchar(50),
user_id int references user (user_id) on delete cascade
);
Ideally you should configure cascading deletion such that when a record is deleted from the user table all dependent records are also deleted from the buy_product table. In lieu of that, we can try doing a delete join here:
DELETE u, bp
FROM user u
INNER JOIN buy_product bp
ON bp.user_id = u.user_id
WHERE u.user_id = 2;

How to change duplicate rows to unique values in mysql databse

I have a database table with about 1M records. I need to find all duplicate names in this table and make them unique.
Id Name
1 A
2 A
3 B
4 C
5 C
Should be changed to...
Id Name
1 A
2 A-1
3 B
4 C
5 C-1
Is there an effective way of doing this with a mysql query or procedure?
Thanks in advance!
I needed to do something similar to a table I was just working on. I needed a unique URL field but the previous keepers of the data did not keep these constraints. The key was to create a temp table.
I used this response here to help: MySQL Error 1093 - Can't specify target table for update in FROM clause
Take note that it doesn't perform well, but then again if you only need to run it once on a database to clean a table then it shouldn't be so bad.
UPDATE `new_article` `upd`
SET `upd`.`url` = CONCAT(`upd`.`url`, '-', `upd`.`id`)
WHERE `upd`.`url` IN(
SELECT `url` FROM (
SELECT `sel`.`url` FROM `new_article` `sel`
GROUP BY `sel`.`url` HAVING count(`sel`.`id`) > 1
) as `temp_table`
);

Select records based on multiple value of foreign key

i am currently writing query. i want to select all records from table . records will be based on mutiple values of foreign key. for example all records related to 1 and 2 both
eg. table might have
id name uid
1 bil 3
2 test 3
3 test 4
4 test 4
5 bil 5
6 bil 5
i want to select all records related to 3 but also related to 4 in this case it is record number 2
SELECT id
FROM `table`
WHERE uid = value1 AND like_id
IN (SELECT like_id
FROM likes
WHERE uid = uid2)
LIMIT 0 , 30
It's not at all clear where "value1" is coming from, or "uid2" is coming from, or where the column "like_id" is coming from. Those column names do not appear in your sample table. Your example query references two different table names (table and likes), yet you only show data for one example table, and that table does not have a column named like_id.
If we assume that "value1" and "uid2" in your query are literals, or bind parameters supplied to the query, which seems to be reasonable, given your specification (variously), of values of 1,2,3 and 4. But we're still left with "like_id" column. Given that it's referenced in the SELECT list of the IN subquery, we're going to presume that's a column in the "likes" table, and given that it's referenced in the outer query, we're going to assume that it's a column in the (unfortunately named) table table.
(Bottomline, it's not at all clear how your query is returning a "correct" result, given that you've made it impossible to replicate a working test case.)
Given a single table, as shown in your example data, e.g.
CREATE TABLE likes (id INT, name VARCHAR(4), uid INT);
INSERT INTO likes VALUES (1,'bil',3),(2,'test',3),(3,'test',4)
,(4,'test',4),(5,'bil',5),(6,'bil',5);
ALTER TABLE likes ADD PRIMARY KEY (id);
ALTER TABLE likes ADD CONSTRAINT likes_ix UNIQUE KEY (uid, name);
Assuming that we're running a query against that single table, and that we're matching "likes" associated with uid=3 to "likes" associated with uid=4, and that the matching is done on the "name" column, then
SELECT t.id
FROM `likes` t
WHERE t.uid = 3
AND EXISTS
( SELECT 1
FROM `likes` s
WHERE s.name = t.name
AND s.uid = 4
)
That will return the id of the row from the likes table for uid=3 where we also find a row in the likes table for uid=4 with a matching name value.
Given a limited number of rows to be inspected from the likes table on the outer query, that gives a limited number of times a correlated subquery would need to be run, which should give reasonable performance:
For large sets, a join operation generally performs better to return an equivalent result:
SELECT t.id
FROM `likes` t
JOIN `likes` s
ON s.name = t.name
AND s.uid = 4
WHERE t.uid = 3
GROUP
BY t.id
The key to optimum performance for either query is going to be appropriate indexes.

Multiple unique entries on table update mysql

Right now I have a table with an auto increment id number, a name, and a definition
I am updating the table with values from another table using
INSERT INTO words(id, word, definition) SELECT id, word, definition FROM temp
ON DUPLICATE KEY UPDATE words.word = temp.word, words.definition=temp.definition;
The table temp has the same exact column layout as the table I am using, and it works fine except when I delete an entry from the middle of temp and then update my main table.
For example,
temp
id word definition
1 bob is a cat
2 sam is a dog
3 doug is a monk
4 croe is a bird
table main is set to that
Then I remove row 2 from temp
temp
id word definition
1 bob is a cat
2 doug is a monk
3 croe is a bird
and then update main table
main
id word definition
1 bob is a cat
2 sam is a dog
3 croe is a bird
4 croe is a bird
because temp only has 3 rows now, but main HAD 4, the 4th row isn't deleted. I tried to fix this by making word a unique column, and now I get the error that there is a duplicate entry for key 'word'.
So how do I fix this?
From the MySQL manual,
In general, you should try to avoid using an ON DUPLICATE KEY UPDATE
clause on tables with multiple unique indexes.
so, what you could do is make word your primary key, and get rid of the id column. That should do the trick :)
Your query then becomes
INSERT INTO words(word, definition) SELECT word, definition FROM temp
ON DUPLICATE KEY UPDATE words.word = temp.word, words.definition=temp.definition;
If you need arbitrary sorting, I would create an additional table
CREATE TABLE word_order (VARCHAR(30) PRIMARY KEY, sort_order INT)
and then when you run your queries
SELECT words.word,
words.definition
FROM words
JOIN word_order
ON words.word = word_order.word
ORDER BY word_order.sort_order
Your INSERTS become a little more complicated though, you'd have to run multiple inserts. See sql - insert into multiple tables in one query.
Also, this CodeProject article has some more ideas on the topic.

How to update without altering the structure of table

I have a table which has a structure like as below.
create table test_table (id INT NOT NUll AUTO_INCREMENT
, name varchar(100),
primary key (id))ENGINE=INNODB
Select * from test_table;
id name
1 a
2 b
3 c
Now I want to increment the id by a number lets say 2
So the final results should be
Select * from test_table;
id name
3 a
4 b
5 c
The way I can do it is, first remove the PK and auto increment and then
update the table:
update test_table set id=id+2;
The other way is to make a temp table with out PK and auto increment and then
extract the result to the main table.
Is there any other way to do this without destroying the table structure ?
I am using MYSQL.
In your example, you need to remove the PK first to allow (temporary) duplicate id's during the course of the update.
To avoid duplicates, you must perform an ordered update:
UPDATE test_table SET id = id + 2 ORDER BY id DESC;
This will update records with largest value of id first, hence avoiding collision.
Obviously, if you want to decrement the values of id, then use "ORDER BY id ASC".
Here is the query to update the tables in SQL :- Its generic
UPDATE table_name SET column1=value, column2=value2,WHERE some_column=some_value;
Please follow the link for more information
Update Query
Thanks,
Pavan