[英]MySQL convert many-to-many table into one-to-one
I have a table which is created by joining 2 tables and now the two columns looks like having a many-to-many
relationship.我有一个通过连接 2 个表创建的表,现在这两列看起来像具有many-to-many
关系。 I want to convert this to a one-to-one
relationship meaning, values in both the columns has to be unique
.我想将其转换为one-to-one
关系含义,两列中的值都必须是unique
。 Here is a sample setting;这是一个示例设置;
create table Test(id1 integer, id2 integer);
insert into Test(id1, id2) values(1, 10);
insert into Test(id1, id2) values(1, 20);
insert into Test(id1, id2) values(2, 10);
insert into Test(id1, id2) values(2, 20);
select * from Test;
id1 id1 | id2 id2 |
---|---|
1 1 | 10 10 |
1 1 | 20 20 |
2 2 | 10 10 |
2 2 | 20 20 |
I want to convert the above table into something as below;我想将上表转换为如下内容;
tbl1
id1 id1 | id2 id2 |
---|---|
1 1 | 10 10 |
2 2 | 20 20 |
OR或者
tbl2
id1 id1 | id2 id2 |
---|---|
1 1 | 20 20 |
2 2 | 10 10 |
How to write a SQL query to convert test
table to tbl1
or tbl2
?如何编写 SQL 查询将test
表转换为tbl1
或tbl2
?
This will take out unique values as mentioned in the comments on my other answer.这将取出我在其他答案的评论中提到的独特价值。
SELECT a.id1, b.id2
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY id1) AS RowNum FROM (SELECT DISTINCT id1 FROM test) x
) AS a,
(
SELECT *, ROW_NUMBER() OVER (ORDER BY id2) AS RowNum FROM (SELECT DISTINCT id2 FROM test) x
) AS b
WHERE a.RowNum = b.RowNum
Let me know if there is something I misunderstood.如果有什么我误解了,请告诉我。
Ok.好的。 To force the table to have unique columns you can just add a unique index on the table.要强制表具有唯一列,您只需在表上添加唯一索引。 (Feel free to change to better name on the index). (随时更改为索引上更好的名称)。
CREATE UNIQUE INDEX my_index_name_1 ON test(id1);
CREATE UNIQUE INDEX my_index_name_2 ON test(id2);
Then the indexes will not allow any duplicates.然后索引将不允许任何重复。 (There can't be any duplicates when you create the indexes above.) (创建上面的索引时不能有任何重复。)
But....if you have full control over the database it seems a bit strange to have this type of table if there are only 1 to 1 relations.但是....如果您可以完全控制数据库,那么如果只有 1 对 1 的关系,拥有这种类型的表似乎有点奇怪。 Then you could just add a fields on the two main tables instead.然后你可以在两个主表上添加一个字段。
If the ids are coming from the tables 'Table1' and 'Table2' you can have a field in Table1 which are called table2_id and pointing to the row in table2.如果 id 来自表 'Table1' 和 'Table2' 你可以在 Table1 中有一个名为 table2_id 的字段并指向 table2 中的行。 And in the Table2 you could have a field called table1_id and that would point to table1.在 Table2 中,您可以有一个名为 table1_id 的字段,它将指向 table1。 Then you could just skip this table and all searches would be faster.然后你可以跳过这个表,所有的搜索都会更快。 But of course there might be a reason this is not possible.但当然,这可能是有原因的。 Just wanted to mention it anyways...反正就是想提一下...
I misunderstood the question at first, so this is my new answer.我一开始误解了这个问题,所以这是我的新答案。 As I understand it you want to remove rows so the only rows left are unique and it does not matter which rows are deleted?据我了解,您想删除行,所以剩下的唯一行是唯一的,删除哪些行并不重要? If so, this solution will work:如果是这样,此解决方案将起作用:
DELETE test
FROM test
JOIN (
SELECT * FROM (
SELECT t.id1, t.id2, (SELECT MAX(id2) FROM test WHERE id1 = t.id1) AS maxId2
from test t
) AS r
WHERE r.id2 != maxId2
) d
ON d.id1 = test.id1 AND d.id2 = test.id2;
This query will delete all rows except the ones with the highest id2.此查询将删除除具有最高 id2 的行之外的所有行。 Please test it and make a backup before running it, I have of course tested it on my side but still.请在运行之前对其进行测试并进行备份,我当然已经在我身边测试过它,但仍然如此。
Relational databases do not recommend/allow many to many relationships by design.关系数据库在设计上不推荐/允许多对多关系。 However, for this specific requirement, following code should get closer to what you want.但是,对于这个特定的要求,下面的代码应该更接近你想要的。 Code is on a dbfiddle代码在dbfiddle
create table tb11(id1 integer, id2 integer);
create table tb12(id1 integer, id2 integer);
INSERT INTO tb11
SELECT id1, id2 FROM
(SELECT
id1,
id2,
RANK() OVER (PARTITION BY id2 ORDER BY id1 ASC) as rnk
FROM
Test) t1 where t1.rnk = 1;
INSERT INTO tb12
SELECT id1, id2 FROM
(SELECT
id1,
id2,
RANK() OVER (PARTITION BY id2 ORDER BY id1 ASC) as rnk
FROM
Test) t2 where t2.rnk = 2;
SELECT * FROM tb11;
SELECT * FROM tb12;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.