Пытаюсь заставить мой оператор удаления работать

Я хочу удалить строки из таблицы на основе столбца из другой таблицы как таковой:

Table1:            Table2:
value              value, i

Если table2.i меньше 1, удалите соответствующую строку из table1 (но оставьте ее в table2).

Проблема в том, что значение не уникальное, поэтому, если у меня есть это, например:

 Table1            table2
+-------+        +-----------+
| value |        | value | i |
+-------+        +-----------+
|   5   |        |  5    | 0 |
|   3   |        |  5    | 3 |
+-------+        |  3    | 0 |
                 |  3    | 0 |
                 +-----------+

Значение 3 должно быть удалено из таблицы1 (поскольку все вхождения в таблице2 имеют i ‹1), но значение 5 должно остаться (из-за того, что строка i = 3 в таблице2)

Мой код пока (не работает):

DELETE FROM Table1, Table2
WHERE (SELECT MIN(Table2.i) FROM Table1, Table2
       WHERE Table1.value = Table2.value) < 1;

Проблема: поскольку мой подзапрос возвращает min для ВСЕХ строк, все удаляется.

И я не могу использовать «группировать по» в моем подзапросе, потому что тогда мое сравнение не разрешено.


person Johan Hjalmarsson    schedule 14.06.2013    source источник
comment
Какую СУБД вы используете? RDBMS означает Система управления реляционными базами данных. RDBMS is the basis for SQL, и для всех современных систем баз данных, таких как MS SQL Server, IBM DB2, Oracle, MySQL и т. Д.   -  person John Woo    schedule 14.06.2013
comment
Я использую версию SQL: 11.0.2100.60 (студия управления Microsoft SQL Server)   -  person Johan Hjalmarsson    schedule 14.06.2013


Ответы (4)


Попробуй это:

DELETE FROM Table1 
WHERE NOT EXISTS(SELECT 1  
                   FROM Table2          
                  WHERE Table2.i > 0 
                    AND Table2.value = Table1.value)
person Nilesh Nikumbh    schedule 14.06.2013

Я не знаю, почему вы используете min, вместо этого вы должны использовать max:

попробуй это

     DELETE FROM Table1
   WHERE Table1.value1 = Table2.value1
   and (SELECT MAX(Table2.i) FROM Table2
   WHERE Table1.value1 = Table2.value1) < 1;
person cosmos    schedule 14.06.2013

Хорошо, я бы начал с написания запроса, который выбирает строки, которые вы хотите удалить,

SELECT
            *
    FROM
       Table1
    EXCEPT
    (
    SELECT
                t1.value
        FROM
                Table1 t1
            JOIN
                Table2 t2
                    ON t2.value = t1.value
        WHERE
                t2.i > 0
    );

См. Fiddle

Затем измените SELECT на DELETE

DELETE Table1
    FROM
       Table1 t1
    WHERE
       t1.value NOT IN
    (
    SELECT
                t1.value
        FROM
                Table1 t1
            JOIN
                Table2 t2
                    ON t2.value = t1.value
        WHERE
                t2.i > 0
    );

См. Fiddle

person Jodrell    schedule 14.06.2013

Как насчет:

delete from table1 where value in
    (select value from table2 group by value having max(i) < 1)

Группировка таблицы 2 по значению и использование having для определения того, где максимум меньше 1, позволяет выбрать правильные значения для удаления из таблицы 1.

having - это, по сути, предложение where, которое вступает в действие после агрегирования, поэтому может использоваться с max и т. Д.

Вот сценарий, чтобы показать это в действии:

DROP TABLE TABLE1;
DROP TABLE TABLE2;
CREATE TABLE TABLE1 (VALUE INTEGER);
CREATE TABLE TABLE2 (VALUE INTEGER, I INTEGER);
INSERT INTO TABLE1 VALUES (5);
INSERT INTO TABLE1 VALUES (3);
INSERT INTO TABLE2 VALUES (5, 0);
INSERT INTO TABLE2 VALUES (5, 3);
INSERT INTO TABLE2 VALUES (3, 0);
INSERT INTO TABLE2 VALUES (3, 0);

SELECT * FROM TABLE1;
SELECT * FROM TABLE2;

DELETE FROM TABLE1 WHERE VALUE IN
  (SELECT VALUE FROM TABLE2 GROUP BY VALUE HAVING MAX(I) = 0);

SELECT * FROM TABLE1;
SELECT * FROM TABLE2;

Результат этого сценария показан ниже. Во-первых, настройка всех таблиц:

DROP TABLE TABLE1; DROP TABLE TABLE2;
    TABLE1 DROPPED
    TABLE2 DROPPED
CREATE TABLE TABLE1 (VALUE INTEGER);
    TABLE1 CREATED
CREATE TABLE TABLE2 (VALUE INTEGER, I INTEGER);
    TABLE2 CREATED
INSERT INTO TABLE1 VALUES ((5), (3));
    INSERTED 2 ROWS
INSERT INTO TABLE2 VALUES ((5, 0), (5, 3), (3,0), 3, 0));
    INSERTED 4 ROWS

И отобразите их, чтобы убедиться, что они ожидаются:

SELECT * FROM TABLE1; SELECT * FROM TABLE2;
    VALUE
    -----
      5
      3
    VALUE   I
    -----   -
      5     0
      5     3
      3     0
      3     0

Затем запустите команду, чтобы избавиться от соответствующих строк:

DELETE FROM TABLE1 WHERE VALUE IN                          
  (SELECT VALUE FROM TABLE2 GROUP BY VALUE HAVING MAX(I) = 0);
    DELETED 1 ROW

И вы можете видеть, что 3` строка исчезла из таблицы 1, как и нужно:

SELECT * FROM TABLE1; SELECT * FROM TABLE2;
    VALUE
    -----
      5
    VALUE   I
    -----   -
      5     0
      5     3
      3     0
      3     0
person paxdiablo    schedule 14.06.2013
comment
Я жалуюсь на точку с запятой. Говорит: Ожидая ')', EXCEPT или UNION - person Johan Hjalmarsson; 14.06.2013
comment
SELECT * FROM TABLE1 WHERE TABLE1.value IN (SELECT table2.value from table2 GROUP BY table2.value HAVING MAX (table2.i) ‹1) AND TABLE1.Value2 IN (SELECT Table2.value2 from table2 GROUP BY table2.value2 HAVING MAX (table2.i) ‹1); - person Johan Hjalmarsson; 14.06.2013
comment
На самом деле должны совпадать 2 значения, но я не думал, что это будет иметь значение, поэтому просто спросил, как это сделать с одним. - person Johan Hjalmarsson; 14.06.2013