Migrate data from a link table into target table - mysql

I have two tables. One (let's call it a) is currently a link table with data in like this
| c_id | t_id |
|-------|-------|
| 1 | 8 |
| 1 | 9 |
| 2 | 8 |
| 3 | 8 |
| 4 | 9 |
and another (t) with data like this
| id | code | value |
|-------|-------|-------|
| 1 | AB | 0.9 |
| 2 | BC | 0 |
| 3 | IM | 0 |
| 4 | MC | 0 |
| 5 | VI | 0 |
| 6 | BC | 0.9 |
| 7 | MC | 2.5 |
| 8 | VI | 2.5 |
| 9 | BC | 2.5 |
t_id in table a is a foreign key mapping onto id in table t, which is an auto incremented ID.
Due to functionality changes, I now want the data from a to replicate the linked row in t and add the required c_id (and then table a to be dropped) so you get something like this;
| id | c_id | code | value |
|-------|-------|-------|-------|
...
| 25 | 1 | VI | 2.5 |
| 26 | 2 | VI | 2.5 |
| 27 | 3 | VI | 2.5 |
| 28 | 1 | BC | 2.5 |
| 29 | 4 | BC | 2.5 |
which will enable me to change the value column per c_id, rather than globally. The new rows can safely be added to the end of the table - or perhaps it would be better to have a new table with this information in.
Is there a query that can do this? I hope I don't have to do it by hand!

Assuming I'm understanding correctly, since you mentioned modifying tables, this is a one-time procedure.
You won't be able to add the rows to the end of either of the existing tables, since you have different column requirements. You'll have to either make a new table or modify the existing one. I chose the former, and then you can populate it using CREATE TABLE ... SELECT ... syntax:
CREATE TABLE new_t (id SERIAL, c_id INT, code VARCHAR(2), value FLOAT);
INSERT INTO new_t (c_id, code, value)
SELECT a.c_id, t.code, t.value FROM a INNER JOIN t ON (t.id = a.t_id);
http://sqlfiddle.com/#!9/c6765/2

Related

MYSQL Insert into table's column based on column name

For some reason I am having difficulty wording this question but I will try my best. I've been searching for 2 days on and off now and haven't found a good solution to the issue.
I have a Table called InventoryNode;
_________________________________________________
| InvID | ID | Slot | ItemID1 | ItemID2 | ItemID3 |
|-------|----|------|---------|---------|---------|
| 1 | 1 | Neck | 10 | 22 | 66 |
| 1 | 2 | Head | 26 | 23 | 56 |
| 1 | 3 | Leg | 19 | 21 | 76 |
And another table called Inventory which stores the Node ID in each column
_____________________________
| ID| Neck | Head | Leg | ... |
|---|------|------|-----|-----|
| 1 | 1 | 2 | 3 | 66 |
If there a way I can insert the node ID's into the Inventory table based off the InvID and populate all the columns with the correct name with the Node's ID?
Something like this?
INSERT INTO Inventory INNER JOIN InventoryNode ON
(Inventory.ID = InventoryNode.InvID) WHERE Inventory.column_name =
InventoryNode.Slot SET InventoryNode.InvID

How to make a pivot table by multiple unique ID numbers?

I'm trying to break up a SQL table that needs to take a users name and find the unique user ID's from up to 4 systems.
The data is currently like this:
| Name | User_ID |
-----------------
| A | 10 |
| A | 110 |
| A | 1500 |
| A | 4 |
| B | 20 |
| B | 100 |
| B | 2 |
| C | 10 |
I need to pivot it around the user's name to look like this (the id's don't need to be in numerical order as the SYS#_ID for each doesn't matter):
| Name | SYS1_ID | SYS2_ID | SYS3_ID | SYS4_ID |
------------------------------------------------
| A | 4 | 10 | 110 | 1500 |
| B | 2 | 20 | 100 | NULL |
| C | 10 | NULL | NULL | NULL |
This is the code I have tried on MySQL:
PIVOT(
COUNT(User_ID)
FOR Name
IN (SYS1_ID, SYS2_ID, SYS3_ID, SYS4_ID)
)
AS PivotedUsers
ORDER BY PivotedUsers.User_Name;
I'm unsure if PIVOT works on MySQL as I keep getting an error "PIVOT unknown". Is there a way to find the values that each user has and if they do not appear in the table already add them to the next column with a max of 4 values?

Creating a HIVE table that filters data from a .csv in HDFS based on the value in a column

I currently have a file which contains data in it that needs to populate 9 different tables. Each of these tables has a different number of columns and datatypes, therefore I need to filter the source file (using the first column which determines which table the row will go into).
My current method is to create a table that has generic columns names col_1, col_2 etc up to the last filled column in the file and then create 9 views that reference this file. The issue I have is that there are a different data types appearing in the same columns due to the fact the tables are all different structures.
Is there a possibility to create a dynamic schema that filters the .csv that the HIVE table points to base on the first column??
thanks
Demo
data.csv
1,1,Now,11,22,2016-12-12
1,2,I,33,44,2017-01-01
3,3,heard,55,66,2017-02-02
1,4,you,77,88,2017-03-03
2,5,know,99,1010,2017-04-04
1,6,that,1111,1212,2017-05-05
2,7,secret,1313,1414,2017-06-06
create external table mycsv
(
rec_type int
,id int
,mystring string
,myint1 int
,myint2 int
,mydate date
)
row format delimited
fields terminated by ','
stored as textfile
;
select * from mycsv;
+----------+----+----------+--------+--------+------------+
| rec_type | id | mystring | myint1 | myint2 | mydate |
+----------+----+----------+--------+--------+------------+
| 1 | 1 | Now | 11 | 22 | 2016-12-12 |
| 1 | 2 | I | 33 | 44 | 2017-01-01 |
| 3 | 3 | heard | 55 | 66 | 2017-02-02 |
| 1 | 4 | you | 77 | 88 | 2017-03-03 |
| 2 | 5 | know | 99 | 1010 | 2017-04-04 |
| 1 | 6 | that | 1111 | 1212 | 2017-05-05 |
| 2 | 7 | secret | 1313 | 1414 | 2017-06-06 |
+----------+----+----------+--------+--------+------------+
create table t1(id int,mystring string);
create table t2(id int,mystring string,mydate date);
create table t3(id int,mydate date,myint1 int,myint2 int);
from mycsv
insert into t1 select id,mystring where rec_type = 1
insert into t2 select id,mystring,mydate where rec_type = 2
insert into t3 select id,mydate,myint1,myint2 where rec_type = 3
select * from t1;
+----+----------+
| id | mystring |
+----+----------+
| 1 | Now |
| 2 | I |
| 4 | you |
| 6 | that |
+----+----------+
select * from t2;
+----+----------+------------+
| id | mystring | mydate |
+----+----------+------------+
| 5 | know | 2017-04-04 |
| 7 | secret | 2017-06-06 |
+----+----------+------------+
select * from t3;
+----+------------+--------+--------+
| id | mydate | myint1 | myint2 |
+----+------------+--------+--------+
| 3 | 2017-02-02 | 55 | 66 |
+----+------------+--------+--------+

MySql Update Row and it's "Descendants"

I'm having trouble figuring out how to update the descendants/children of a row.
Example table, named test
+----+--------+------+
| Id | Parent | Val |
+----+--------+------+
| 1 | 0 | |
| 2 | 1 | |
| 3 | 1 | |
| 4 | 1 | |
| 5 | 0 | |
| 6 | 5 | |
| 7 | 6 | |
| 8 | 6 | |
| 9 | 0 | |
+----+--------+------+
What I'd like to have done is, when Val is set to something, update every row that is related to that row. For example, If I ran
UPDATE test SET Val=1 WHERE Id=5;
I want Val in the rows where the Id is 6, 7, and 8, to also be 1.
The best thing I could come up with was
UPDATE test t1
JOIN test t2 ON t1.Id = t2.Parent
JOIN test t3 ON t2.Id = t3.Parent
SET t1.Val=1, t2.Val=1, t3.Val=1 WHERE t1.Id=5;
+----+--------+------+
| Id | Parent | Val |
+----+--------+------+
| 1 | 0 | |
| 2 | 1 | |
| 3 | 1 | |
| 4 | 1 | |
| 5 | 0 | 1 |
| 6 | 5 | 1 |
| 7 | 6 | 1 |
| 8 | 6 | 1 |
| 9 | 0 | |
+----+--------+------+
This gives me what I want, but I'm afraid it's poor practice and it doesn't account for a variable depth. What can I do here? I thought a trigger may have been the answer, but that didn't seem to be possible. I got the error "Can't update table in stored function/trigger because it is already used by statement which invoked this stored function/trigger"
It's pretty awkward to handle this kind of case with MySQL, because MySQL doesn't support recursive queries.
I solve this problem by storing the hierarchy as a transitive closure, instead of the "parent_id" style you're using. See my answer to What is the most efficient/elegant way to parse a flat table into a tree?
Then you can update all descendants of a given node in the heirarchy:
UPDATE test JOIN testclosure AS c ON test.id = c.descendant
SET test.val = 1
WHERE c.ancestor = 5;

SQL INSERT INTO query syntax

I am trying to run an MySQL query to copy over data from an old table (ps__product_review/rate) to a new table (ps_product_comment/grade) based on review ID (id_product_comment). But I am a bit lost on the SQL query, this is what I have but keep getting errors.
INSERT INTO ps_product_comment [(grade)]
SELECT rate
FROM ps__product_review
[WHERE ps__product_review.id_product_comment=ps_product_comment.id_product_comment];
Can anyone help write the correct query?
Edit:Essentially I am trying to populate the Grade column in the new table below.
Old table (ps__product_review)
+--------------------+----------+-----+
| id_product_comment | Comment | Rate|
+--------------------+----------+-----+
| 1 | Good | 2 |
| 2 | Great | 5 |
| 3 | OK | 3 |
| 4 | Brill | 4 |
| 5 | OK | 3 |
| 6 | Average | 2 |
| 7 | Bad | 1 |
+--------------------+----------+-----+
New Table (ps_product_comment)
+--------------------+----------+-------+
| id_product_comment | Comment | Grade |
+--------------------+----------+-------+
| 1 | Good | |
| 2 | Great | |
| 3 | OK | |
| 4 | Brill | |
| 5 | OK | |
| 6 | Average | |
| 7 | Bad | |
+--------------------+----------+-------+
If you want to update table with data from another table, use UPDATE with JOIN
UPDATE ps_product_comment
JOIN ps__product_review
ON ps__product_review.id_product_comment = ps_product_comment.id_product_comment
SET ps_product_comment.grade = ps__product_review.rate;
Remove the square brackets and I think you are missing the JOIN(since you are using that in your where clause):
INSERT INTO ps_product_comment (grade)
SELECT rate
FROM ps__product_review inner join ps_product_comment on
ps__product_review.id_product_comment=ps_product_comment.id_product_comment;