Frage

Ich habe eine Tabelle wie folgt bekommen:

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

Jetzt mein Problem ist, dass 1 - 2 bedeutet die gleichen wie 2 - 1 (look @ ID 1 und ID 3 zum Beispiel), und ich möchte alle Einträge beseitigen, in denen Wert 1 - Wert 2 bedeutet die gleichen wie Wert 2 - Wert1 (hoffen, dass Sie meine Logik hier folgen konnte).

War es hilfreich?

Lösung

Wie wäre es damit:

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));

Ich hielt willkürlich die Zeile mit dem größten ID-Wert.

Beispiel:

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> 

Einfache Anpassung verschiedene Reihen zu halten, zum Beispiel

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: Könnte nicht eine wirklich cleveren Art und Weise denken, also hier die Brute-Force-Methode, um die Frage in Ihrem Kommentar zu beantworten:

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

Andere Tipps

Ich erinnere mich nicht, wenn diese Syntax in Oracle gültig ist oder nicht (meist die Verwendung eines Alias ??für die DELETE subject), aber man kann versuchen, diese:

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

Da die Reihenfolge der Spalten ist keine Rolle zu spielen, würde ich eine willkürliche Entscheidung treffen, und ich würde eine Einschränkung der Tabelle hinzufügen zu prüfen, ob val1

Natürlich müssten Sie auch sicherstellen, dass jede Anwendung oder Code, fügt Zeilen in der Tabelle, weiß, dass Konvention (val1 immer die kleinste der beiden Werte sein sollte) und folgt ihr.

Wenn Mittel beseitigen nicht zeigen, versuchen Sie dies, wird dies nicht wieder alle Zeilen für diese Bedingungen

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

Es gibt eine Ecke Fall, die nicht gut hier behandelt wird. Das ist der Fall, in dem Val1 und Val2 gleich ist. Löschen aller aber ein Auftreten solcher Reihen ist ein bisschen schwieriger. Wer irgendwelche Ideen?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top