كيف تُعمل على قيم Elmininate في طاولة Oracle-SQL التي تعني نفس الشيء؟

StackOverflow https://stackoverflow.com/questions/3479782

  •  28-09-2019
  •  | 
  •  

سؤال

لدي طاولة مثل هذا:

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 (انظر @ @ المعرف 1 والمعرف 3 على سبيل المثال) وأريد التخلص من جميع الإدخالات حيث القيمة 1 - القيمة 2 تعني نفس القيمة 2 - القيمة 1 (الأمل يمكنك متابعة منطقي هنا).

هل كانت مفيدة؟

المحلول

وماذا عن هذا:

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

احتفظت بشكل تعسفي بالصف مع أكبر قيمة هوية.

مثال:

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

تحديث: لا يمكن التفكير في طريقة ذكية حقًا ، لذا إليك طريقة القوة الغاشمة للإجابة على السؤال في تعليقك:

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

نصائح أخرى

لا أتذكر ما إذا كان هذا الجملة صالحًا في Oracle أم لا (في الغالب استخدام الاسم المستعار لموضوع الحذف) ، ولكن يمكنك تجربة هذا:

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 <Val2. يمكنك بعد ذلك وضع قيود فريدة على مزيج من العمودين (إذا لم يكن لديك واحد بالفعل) وتأكد من أنك لن تواجه هذه المشكلة مرة أخرى.

بالطبع ، ستحتاج أيضًا إلى التأكد من أن أي تطبيق أو رمز يقوم بإدراج الصفوف في الجدول يعرف أن الاتفاقية (يجب أن تكون Val1 دائمًا أصغر القيمتين) وتتبعها.

إذا تعني التخلص من عدم العرض ، فحاول ذلك ، فلن يؤدي ذلك إلى إرجاع أي صفوف لتلك الشروط

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)

هناك حالة زاوية لا يتم التعامل معها بشكل جيد هنا. هذا هو الحال حيث تكون Val1 و Val2 متساوية. حذف كل ما عدا حدوث مثل هذه الصفوف أمر أصعب بعض الشيء. هل لدي احد اى افكار؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top