mysql copy one row data into multiple rows - mysql

I have a table such as:
PK FK Value1 value2 value3
1 1 3 2 5
2 2 5 3 6
4 1 9 null 5
I want a query to copy all rows into resulting table, except those that have a null value.
Resulting in:
PK(above table) value(PK)
1 3
1 2
1 5
2 5
2 3
2 6
4 9
4 5

One way is to do it as three inserts, controlled by a transaction if you need atomicity on the operation:
begin
insert into newtable (pk, value) select pk, value1 from oldtable
where value1 is not null
insert into newtable (pk, value) select pk, value2 from oldtable
where value2 is not null
insert into newtable (pk, value) select pk, value3 from oldtable
where value3 is not null
commit
That's of course assuming your primary key on the new table crosses both columns (I suspect it is since your second column has pk as well). If it's just on pk, no solution is going to work since you'll have a primary key constraint violation.
You can also do it as a union:
insert into newtable (pk, value)
select pk, value1 from oldtable where value1 is not null
union select pk, value2 from oldtable where value2 is not null
union select pk, value3 from oldtable where value3 is not null

You can wirte below queries to achive this
INSERT INTO TABLE2 (SELECT ID,VALUE1 FROM table1);
INSERT INTO TABLE2 (SELECT ID,VALUE2 FROM table1);
INSERT INTO TABLE2 (SELECT ID,VALUE3 from table1);
If you need Single query then you can use
INSERT INTO TABLE2 (SELECT ID,COLUMN1 FROM table1 UNION SELECT ID,COLUMN2 FROM table1 UNION SELECT ID,COLUMN3 from table1)

Related

Preferential Select Query

The issue that we are trying to tackle is best shown with the following illustrative example:
CREATE TABLE table_1
(
id INT UNSIGNED AUTO_INCREMENT,
colA INT,
colB VARCHAR(10),
PRIMARY KEY(id)
);
CREATE TABLE table_2
(
id INT UNSIGNED AUTO_INCREMENT,
colY INT,
colZ VARCHAR(10),
PRIMARY KEY(id)
);
INSERT INTO table_1(colA, colB) VALUES(1, 'NPD5A6V9EI'), (2, 'ISO4IK42YQ'), (4, 'J12QAN4O42'), (6,'V8YTZFHCU4');
INSERT INTO table_2(colY, colZ) VALUES(3, 'RBUNWLO753'), (4, 'X2BCEY7O8B'), (5, 'BNUS7R4225'), (6, '72NOWCTH5G');
We would like to select our result based on the value of colA in table_1 but if that does not return a result , we would like to return our result based on the value of colY in table_2. In other words SELECTing from table_2 is the backup for SELECTing from table_1. The query returns NULL only if neither table satisfies the condition.
A pseudo SQL query could be:
SELECT colB FROM table_1 where colA = 3 OR SELECT colZ FROM table_2 where colY = 3;
The query should return output based on the following I/O table:
I O
= =
1 NPD5A6V9EI -- From table_1
2 ISO4IK42YQ -- From table_1
3 RBUNWLO753 -- From table_2
4 J12QAN4O42 -- From table_1 (has precedence over table_2 entry)
5 BNUS7R4225 -- From table_2
6 V8YTZFHCU4 -- From table_1 (has precedence over table_2 entry)
9 NULL
Kindly suggest solutions that:
make use of the latest DB features (for posterity)
work with MySQL version 5.6.51 (for our application)
Write a subquery that generates all the I rows that you want.
Then left join this with the two tables, and use IFNULL to take the matching value from table_1 in preference to table_2.
SELECT ids.id AS I, IFNULL(t1.colB, t2.colZ) AS O
FROM (SELECT 1 AS id UNION ALL SELECT 2 UNION ALL SELECT 3 ... UNION ALL SELECT 9) AS ids
LEFT JOIN table_1 AS t1 ON t1.colA = ids.id
LEFT JOIN table_2 AS t2 ON t2.colY = ids.id
ORDER BY ids.id
I simply don't kn ow where you get your last row.
also with Myql 8 you can ise the window function ROW_NUMBER
the rest is self explantory, the sorting comes from colA and Col1, when there are teh same numbers the second column orderby2 comes and sorts first for the first table
CREATE TABLE table_1
(
id INT UNSIGNED AUTO_INCREMENT,
colA INT,
colB VARCHAR(10),
PRIMARY KEY(id)
);
CREATE TABLE table_2
(
id INT UNSIGNED AUTO_INCREMENT,
colY INT,
colZ VARCHAR(10),
PRIMARY KEY(id)
);
INSERT INTO table_1(colA, colB) VALUES(1, 'NPD5A6V9EI'), (2, 'ISO4IK42YQ'), (4, 'J12QAN4O42'), (6,'V8YTZFHCU4');
INSERT INTO table_2(colY, colZ) VALUES(3, 'RBUNWLO753'), (4, 'X2BCEY7O8B'), (5, 'BNUS7R4225'), (6, '72NOWCTH5G');
SELECT #i := #i +1 AS I,
colB AS O
FROM
(SELECT colA as orderby1,colB,1 ordberby2 froM table_1
UNION
SELECT colY, colZ,2 froM table_2 ) t1,(SELECT #i := 0) t2
ORDER BY orderby1,ordberby2
I | O
-: | :---------
1 | NPD5A6V9EI
2 | ISO4IK42YQ
3 | RBUNWLO753
4 | J12QAN4O42
5 | X2BCEY7O8B
6 | BNUS7R4225
7 | V8YTZFHCU4
8 | 72NOWCTH5G
db<>fiddle here

Selecting distinct 5 columns combination in mysql

I have a mysql table that looks like this: Col 1 is UNIQUE.
1 value1 value2 0 2
2 value1 value2 1 3
3 value3 value4 3 2
4 value4 value5 4 1
5 value3 value4 3 1
I need a query to select all the rows with distinct column 1 and 2, for example the output I want for this example will look like this:
1 value1 value2 0 2
3 value3 value4 3 2
4 value4 value5 4 1
I need distinct col 1 and 2 but altogether all columns combination will be distinct always. I want to display distinct col 1,2 and 3 without col 2,3 repeating.
I've found a few samples on how to do it but they all select distinct on each column individually. I tried many stackoverflow answers too. But my question is different.
One method that performs well is a correlate subquery:
select t.*
from t
where t.col1 = (select min(t2.col1)
from t t2
where t2.col2 = t.col2 and t2.col3 = t.col3
);
For best performance, you want an index on (col2, col3, col1).
I strongly advise having a primary key on all tables, but if you did not have one, then row_number() would be the way to go:
select t.*
from (select t.*,
row_number() over (partition by col2, col3 order by col2) as seqnum
from t
) t
where seqnum = 1;
This incurs a tad more overhead because row numbers need to be assigned to all rows before they are filtered for only first one.
It could be achieved by using ROW_NUMBER:
SELECT *
FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY col2, col3 ORDER BY col1) AS rn
FROM tab) sub
WHERE rn=1

How to insert null value when doing left join in SQL

I have these 2 table (each element is in column):
TABLE A:
ID 1 2 3 4 5
TD 20 10 0 1 7
TABLE B:
ID 2 3
TD 40 30
I want to do a LEFT JOIN to obtain a FINAL_TABLE in which I have all the ID od TABLE A and the one of table B in common with A. I want also that in case there is ID in TABLE A and not in TABLE B (ex. ID 1,4,5), in the FINAL_TABLE I will show NULL at that ID.
The FINAL_TABLE should be (see all in column):
ID 1 2 3 4 5
TDA 20 10 0 1 7
TDB NULL 40 30 NULL NULL
How can I achieve that?
Not quite sure if this is what you ask for, but perhaps you just want to add one result to another?
select 'TDA', col1, col2, col3, col4, col5 from tableA
UNION ALL
select 'TDB', null, col1, col2, null, null from tableB
I think this should work. Could you please try this once.
INSERT INTO FINAL_TABLE
(
ID,
tdA,
tdB
)
SELECT
A.ID,
A.td,
B.td
FROM
TABLEA
LEFT OUTER JOIN TABLEB ON (A.ID=B.ID)
GROUP BY
A.ID,
A.td,
B.td
;

MySQL Delete duplicates in consecutive rows

Suppose this table:
ID ColA ColB
1 7 8
2 7 9
3 7 9
4 5 8
5 6 9
6 6 9
7 5 4
The PK is the ID coumn.
Now, I want to delete all duplicates of ColA and ColB in consecutive rows.
In this example rows 2,3 and 5,6 contain duplicates.
These shall be removed so that the higher ID is remained.
The output should be:
ID ColA ColB
1 7 8
3 7 9
4 5 8
6 6 9
7 5 4
How can this be done with mySQL?
Thanks,
Juergen
SELECT
ID
FROM
MyTable m1
WHERE
0 < (SELECT
COUNT(*)
FROM
MyTable m2
WHERE
m2.ID = m1.ID - 1 AND
m2.ColA = m1.ColA AND
m2.ColB = m1.ColB)
and then you can use a
delete from MyTable where ID in ...
query. This way it would surely work in any version.
CREATE TEMPORARY TABLE duplicates (id int primary key)
INSERT INTO duplicates (id)
SELECT t1.id
FROM table t1
join table t2 on t2.id = t1.id + 1
WHERE t1.ColA = t2.ColA
and t1.ColB = t2.ColB
-- SELECT * FROM duplicates --> are you happy with that? => delete
DELETE table
FROM table
join duplicates on table.id = duplicates.id
Depending on how many records you have, this might not be the most efficient:
SELECT (SELECT TOP 1 id FROM table WHERE colA = m.colA AND colB = m.colB ORDER BY id DESC) AS id, m.*
FROM (SELECT DISTINCT colA, colB
FROM table) m
There might be syntax errors because I usually use mssql, but the idea should be similar.
I've called the first table 'test'.
Firstly create a table that will hold all the identical combinations of ColA and ColB:
create temporary table tmpTable (ColA int, ColB int);
insert into tmpTable select ColA,ColB from test group by ColA, ColB;
Now, select the maximum id in the original table for each identical combination of ColA and ColB. Put this into a new table (called idsToKeep because these are the rows we do not want to delete):
create temporary table idsToKeep (ID int);
insert into idsToKeep select (select max(ID) from test where test.ColA=tmpTable.ColA and test.ColB=tmpTable.ColB) from tmpTable;
Finally, delete all the entries from the original table that are not in the idsToKeep table:
delete from test where ID <> all (select ID from idsToKeep);

SQL query to create many-to-one tables from one table?

I have a table like so:
column1 column2
------- -------
key1 value1
key1 value2
key1 value3
key2 value4
key2 value5
key2 value6
I would like to create the following two tables:
id column1
-- -------
1 key1
2 key2
key_id column2
------ -------
1 value1
1 value2
1 value3
2 value4
2 value5
2 value6
That is, I would like to split a table into a many-to-one relation between two new tables.
How would I write an SQL query to do this?
Assuming the id column in your first new table is an identity column:
INSERT INTO NewTable1
(column1)
SELECT DISTINCT column1
FROM OldTable;
INSERT INTO NewTable2
(key_id, column2)
SELECT n1.id, o.column2
FROM OldTable o
INNER JOIN NewTable1 n1
ON o.column1 = n1.column1;
Why don’t u use php my admin and enter the data manually. It will write the php for you.
Also your id field on each table must always be unique and auto incremented.
you cannot use 111 222 in a primary key