如何消除 Oracle-SQL-Table 中含义相同的值?

发布于 2024-09-14 18:19:16 字数 311 浏览 18 评论 0原文

我有一个这样的表:

ID  |  Val1  |  Val2
---------------------
1   |    1   |   2
2   |    1   |   3
3   |    2   |   1
4   |    2   |   3
5   |    3   |   1
6   |    3   |   2

现在我的问题是,1 - 2 的含义与 2 - 1 相同(例如,查看@ ID 1 和 ID 3),我想消除值 1 - 值 2 含义的所有条目与 value 2 - value1 相同(希望你能遵循我的逻辑)。

I've got a table like this:

ID  |  Val1  |  Val2
---------------------
1   |    1   |   2
2   |    1   |   3
3   |    2   |   1
4   |    2   |   3
5   |    3   |   1
6   |    3   |   2

now my problem is, that 1 - 2 means the same like 2 - 1 (look @ ID 1 and ID 3 for example) and I want to eliminate all entries where value 1 - value 2 means the same like value 2 - value1 (hope you could follow my logic in here).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

独自唱情﹋歌 2024-09-21 18:19:16

怎么样:

DELETE t
 WHERE ID IN 
       (SELECT t1.id
          FROM t t1 JOIN t t2 
                      ON (t1.val1 = t2.val2 AND 
                          t1.val2 = t2.val1 AND 
                          t1.id < t2.id));

我任意保留ID值最大的行。

示例:

SQL> CREATE TABLE t (ID INTEGER, val1 INTEGER, val2 INTEGER);

Table created
SQL> INSERT INTO t VALUES(1,1,2);

1 row inserted
SQL> INSERT INTO t VALUES(2,1,3);

1 row inserted
SQL> INSERT INTO t VALUES(3,2,1);

1 row inserted
SQL> INSERT INTO t VALUES(4,2,3);

1 row inserted
SQL> INSERT INTO t VALUES(5,3,1);

1 row inserted
SQL> INSERT INTO t VALUES(6,3,2);

1 row inserted
SQL> INSERT INTO t VALUES(7,4,4);

1 row inserted
SQL> INSERT INTO t VALUES(8,4,4);

1 row inserted
SQL> SELECT * FROM t;

 ID VAL VAL
--- --- ---
  1   1   2
  2   1   3
  3   2   1
  4   2   3
  5   3   1
  6   3   2
  7   4   4
  8   4   4

8 rows selected
SQL> DELETE t
  2   WHERE ID IN (SELECT t1.id
  3                  FROM t t1 JOIN t t2 ON (t1.val1 = t2.val2 AND t1.val2 = t2.val1 AND t1.id < t2.id));

4 rows deleted
SQL> SELECT * FROM t;

 ID VAL VAL
--- --- ---
  3   2   1
  5   3   1
  6   3   2
  8   4   4

SQL> 

轻松适应保留不同的行,例如

DELETE t
 WHERE ID IN 
       (SELECT t1.id
          FROM t t1 JOIN t t2 
                      ON (t1.val1 = t2.val2 AND 
                          t1.val2 = t2.val1 AND 
                          (t2.val1 < t1.val1 OR (t2.val1 = t1.val1 AND t2.id > t1.id))));

UPDATE:
想不出一个真正聪明的方法,所以这是回答评论中问题的蛮力方法:

CREATE TABLE t (ID INTEGER, val1 INTEGER, val2 INTEGER, val3 INTEGER);

INSERT INTO t VALUES (1, 1, 2, 3);
INSERT INTO t VALUES (2, 1, 3, 2);
INSERT INTO t VALUES (3, 2, 1, 3);
INSERT INTO t VALUES (4, 2, 3, 1);
INSERT INTO t VALUES (5, 3, 1, 2);
INSERT INTO t VALUES (6, 3, 2, 1);
INSERT INTO t VALUES (7, 1, 2, 4);
INSERT INTO t VALUES (8, 1, 3, 5);
INSERT INTO t VALUES (9, 1, 4, 2);
INSERT INTO t VALUES (10, 1, 1, 1);
INSERT INTO t VALUES (11, 1, 1, 1);
INSERT INTO t VALUES (12, 1, 3, 5);

SQL> select * from t order by id;

 ID VAL VAL VAL
--- --- --- ---
  1   1   2   3
  2   1   3   2
  3   2   1   3
  4   2   3   1
  5   3   1   2
  6   3   2   1
  7   1   2   4
  8   1   3   5
  9   1   4   2
 10   1   1   1
 11   1   1   1
 12   1   3   5

12 rows selected

DELETE FROM t 
 WHERE ID IN (SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val1 AND 
                                                   t1.val2 = t2.val2 AND 
                                                   t1.val3 = t2.val3 AND t1.id < t2.id)
              UNION ALL
              SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val1 AND 
                                                   t1.val2 = t2.val3 AND 
                                                   t1.val3 = t2.val2 AND t1.id < t2.id)
              UNION ALL 
              SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val2 AND 
                                                   t1.val2 = t2.val1 AND 
                                                   t1.val3 = t2.val3 AND t1.id < t2.id)
              UNION ALL 
              SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val2 AND 
                                                   t1.val2 = t2.val3 AND 
                                                   t1.val3 = t2.val1 AND t1.id < t2.id)
              UNION ALL 
              SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val3 AND 
                                                   t1.val2 = t2.val1 AND 
                                                   t1.val3 = t2.val2 AND t1.id < t2.id)
              UNION ALL 
              SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val3 AND 
                                                   t1.val2 = t2.val2 AND 
                                                   t1.val3 = t2.val1 AND t1.id < t2.id));

select * from t order by id;

 ID VAL VAL VAL
--- --- --- ---
  6   3   2   1
  9   1   4   2
 11   1   1   1
 12   1   3   5

How about this:

DELETE t
 WHERE ID IN 
       (SELECT t1.id
          FROM t t1 JOIN t t2 
                      ON (t1.val1 = t2.val2 AND 
                          t1.val2 = t2.val1 AND 
                          t1.id < t2.id));

I arbitrarily kept the row with the greatest ID value.

Example:

SQL> CREATE TABLE t (ID INTEGER, val1 INTEGER, val2 INTEGER);

Table created
SQL> INSERT INTO t VALUES(1,1,2);

1 row inserted
SQL> INSERT INTO t VALUES(2,1,3);

1 row inserted
SQL> INSERT INTO t VALUES(3,2,1);

1 row inserted
SQL> INSERT INTO t VALUES(4,2,3);

1 row inserted
SQL> INSERT INTO t VALUES(5,3,1);

1 row inserted
SQL> INSERT INTO t VALUES(6,3,2);

1 row inserted
SQL> INSERT INTO t VALUES(7,4,4);

1 row inserted
SQL> INSERT INTO t VALUES(8,4,4);

1 row inserted
SQL> SELECT * FROM t;

 ID VAL VAL
--- --- ---
  1   1   2
  2   1   3
  3   2   1
  4   2   3
  5   3   1
  6   3   2
  7   4   4
  8   4   4

8 rows selected
SQL> DELETE t
  2   WHERE ID IN (SELECT t1.id
  3                  FROM t t1 JOIN t t2 ON (t1.val1 = t2.val2 AND t1.val2 = t2.val1 AND t1.id < t2.id));

4 rows deleted
SQL> SELECT * FROM t;

 ID VAL VAL
--- --- ---
  3   2   1
  5   3   1
  6   3   2
  8   4   4

SQL> 

Easily adaptable to keep different rows, e.g.,

DELETE t
 WHERE ID IN 
       (SELECT t1.id
          FROM t t1 JOIN t t2 
                      ON (t1.val1 = t2.val2 AND 
                          t1.val2 = t2.val1 AND 
                          (t2.val1 < t1.val1 OR (t2.val1 = t1.val1 AND t2.id > t1.id))));

UPDATE:
Couldn't think of a really clever way, so here's the brute force method to answer the question in your comment:

CREATE TABLE t (ID INTEGER, val1 INTEGER, val2 INTEGER, val3 INTEGER);

INSERT INTO t VALUES (1, 1, 2, 3);
INSERT INTO t VALUES (2, 1, 3, 2);
INSERT INTO t VALUES (3, 2, 1, 3);
INSERT INTO t VALUES (4, 2, 3, 1);
INSERT INTO t VALUES (5, 3, 1, 2);
INSERT INTO t VALUES (6, 3, 2, 1);
INSERT INTO t VALUES (7, 1, 2, 4);
INSERT INTO t VALUES (8, 1, 3, 5);
INSERT INTO t VALUES (9, 1, 4, 2);
INSERT INTO t VALUES (10, 1, 1, 1);
INSERT INTO t VALUES (11, 1, 1, 1);
INSERT INTO t VALUES (12, 1, 3, 5);

SQL> select * from t order by id;

 ID VAL VAL VAL
--- --- --- ---
  1   1   2   3
  2   1   3   2
  3   2   1   3
  4   2   3   1
  5   3   1   2
  6   3   2   1
  7   1   2   4
  8   1   3   5
  9   1   4   2
 10   1   1   1
 11   1   1   1
 12   1   3   5

12 rows selected

DELETE FROM t 
 WHERE ID IN (SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val1 AND 
                                                   t1.val2 = t2.val2 AND 
                                                   t1.val3 = t2.val3 AND t1.id < t2.id)
              UNION ALL
              SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val1 AND 
                                                   t1.val2 = t2.val3 AND 
                                                   t1.val3 = t2.val2 AND t1.id < t2.id)
              UNION ALL 
              SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val2 AND 
                                                   t1.val2 = t2.val1 AND 
                                                   t1.val3 = t2.val3 AND t1.id < t2.id)
              UNION ALL 
              SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val2 AND 
                                                   t1.val2 = t2.val3 AND 
                                                   t1.val3 = t2.val1 AND t1.id < t2.id)
              UNION ALL 
              SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val3 AND 
                                                   t1.val2 = t2.val1 AND 
                                                   t1.val3 = t2.val2 AND t1.id < t2.id)
              UNION ALL 
              SELECT t1.ID FROM t t1 JOIN t t2 ON (t1.val1 = t2.val3 AND 
                                                   t1.val2 = t2.val2 AND 
                                                   t1.val3 = t2.val1 AND t1.id < t2.id));

select * from t order by id;

 ID VAL VAL VAL
--- --- --- ---
  6   3   2   1
  9   1   4   2
 11   1   1   1
 12   1   3   5
下壹個目標 2024-09-21 18:19:16

我不记得这个语法在 Oracle 中是否有效(主要是使用 DELETE 主题的别名),但你可以尝试这个:

DELETE
    T1
FROM
    My_Table T1
INNER JOIN My_Table T2 ON
    T2.val1 = T1.val2 AND
    T2.val2 = T1.val2 AND
WHERE
    T1.val1 < T1.val2

由于列的顺序似乎并不重要,我会做一个任意决定,我会向表添加一个约束来检查 val1 <值2。然后,您可以对两列的组合设置唯一约束(如果您还没有),并确保不会再次遇到此问题。

当然,您还需要确保向表中插入行的任何应用程序或代码都知道该约定(val1 应始终是两个值中最小的一个)并遵循该约定。

I don't recall if this syntax is valid in Oracle or not (mostly the use of an alias for the DELETE subject), but you can try this:

DELETE
    T1
FROM
    My_Table T1
INNER JOIN My_Table T2 ON
    T2.val1 = T1.val2 AND
    T2.val2 = T1.val2 AND
WHERE
    T1.val1 < T1.val2

Since the ordering of the columns doesn't seem to matter, I would make an arbitrary decision and I would add a constraint to the table to check that val1 < val2. You can then put a unique constraint on the combination of the two columns (if you don't already have one) and be sure that you won't have this problem again.

Of course, you would also need to make sure that any application or code that inserts rows into the table knows that convention (val1 should always be the smallest of the two values) and follows it.

挽容 2024-09-21 18:19:16

如果消除意味着不显示,请尝试此操作,这不会返回这些条件的任何行

select * from YourTable t1
where not exists (select * from YourTable t2 
                 where t1.Val1 = t2.Val2 
                 and t1.Val2 = t2.Val1)

If eliminate means not show, try this, this won't return any rows for those conditions

select * from YourTable t1
where not exists (select * from YourTable t2 
                 where t1.Val1 = t2.Val2 
                 and t1.Val2 = t2.Val1)
眼泪淡了忧伤 2024-09-21 18:19:16
delete from YourTable
   where (Val1, Val2)
      in (select Val2, Val1 from YourTable where Val1 > Val2)

这里有一个没有处理好的极端情况。即 Val1 和 Val2 相等的情况。删除除出现一次之外的所有此类行有点棘手。有人有什么想法吗?

delete from YourTable
   where (Val1, Val2)
      in (select Val2, Val1 from YourTable where Val1 > Val2)

There is a corner case that isn't handled well here. That is the case where Val1 and Val2 are equal. Deleting all but one occurrence of such rows is a bit trickier. Anyone have any ideas?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文