2009-11-23 23 views
24

Jest to prawdopodobnie bardzo proste, ale jest poniedziałek rano. Mam dwie tabele:SQL Usuń wiersze na podstawie innej tabeli

Tabela 1:

Field  | Type    | Null | Key | Default | Extra 
id   | int(32) unsigned | NO | PRI | NULL | auto_increment 
group  | int(32)   | NO |  | 0  |     

Table2:

Field  | Type    | Null | Key | Default | Extra 
group  | int(32)   | NO |  | 0  | 

pomijając inne pola ... Chciałbym pojedynczy SQL DELETE, które spowoduje usunięcie wszystkich wierszy w tabeli 1., dla których istnieje grupa Table2.group równa Table1.group. Zatem jeśli wiersz tabeli 1 ma grupę = 69, ten wiersz powinien zostać usunięty, jeśli i tylko wtedy, gdy istnieje wiersz w tabeli 2 z grupą = 69.

Dziękuję za pomoc.

Odpowiedz

35

myślę, że to, co chcesz:

DELETE FROM `table1` 
WHERE `group` in (SELECT DISTINCT `group` FROM `table2`) 
+0

muchos gracias. –

+0

Uratowałem mój dzień! Dziękuję @Jay! – Lefteris

+0

To proste i bardzo skuteczne. Działa na serwerze SQL (ale bez pojedynczych cudzysłowów). –

7

coś takiego

delete from table1 where group in (select group from table2) 
+0

I d wybrać różne w podkwerendy –

+0

Czy nie używasz odrębnych, tylko więcej pracy, aby usunąć duplikaty z podzapytania? Zostawiłbym to. –

1

Off szczycie mojej głowie:

delete from Table1 where id in (select id from table1 inner join table2 on Table1.group = Table2.group) 

Zrobiłem to trochę inaczej niż inne plakaty - Myślę, że jeśli w Tabeli 2 znajduje się duża liczba wierszy, może być lepiej. Czy ktoś może mnie o to prosi?

+0

Ciągle wraca do listy IN, co jest problematyczne. Rozważmy przykład @AmoBrinkman lub BT26; nie wymagają one od silnika dużej tablicy. np. możesz zmienić "id w" na "gdzie istnieje" i prawdopodobnie powinno działać identycznie, ale znacznie szybciej i "w ogóle" dla dużych woluminów. – troy

8

Miłą rozwiązanie jest tylko pisanie SQL jak mówisz to sam już:

DELETE FROM Table1 
WHERE 
    EXISTS(SELECT 1 FROM Table2 WHERE Table2.Group = Table1.Group) 

Pozdrowienia, Arno Brinkman

+1

Podoba mi się to rozwiązanie, które zawiera klauzulę WHERE.Oznacza to, że nadal będzie działać, jeśli chcesz usunąć tylko takie linie, które pasują do kilku kolumn w dwóch tabelach. – malamut

+0

@ArnoBrinkman dodaje "LIMIT 1" do: 'EXISTS (WYBIERZ 1 Z tabeli 2 WHERE Table2.Group = Table1.Group LIMIT 1)' help? –

16

myślę, że ten sposób jest szybszy:

DELETE FROM t1 USING table1 t1 INNER JOIN table2 t2 ON (t1.group = t2.group); 
+0

W SQL Server wydaje się to nie działać: SSMS rzuca to we mnie dla powyższego zapytania: ** Niepoprawna składnia w pobliżu "UŻYWANIA". ** – Oliver

+4

W przypadku SQL Server składnia jest następująca: DELETE FROM t1 ** FROM t1 ** WEJŚCIE WEWNĘTRZNE T2 NA t1.ID = t2.ID Powoduje to usunięcie wszystkich wierszy z t1, które istnieją w tabeli t2 na podstawie identyfikatora, ale więcej warunków można dodać do klauzuli połączenia wewnętrznego jak zwykle z operatorem AND. Zauważ drugi Od ?! Nie jest to przez pomyłkę i to właśnie sprawia, że ​​prace USING na SQL Server. – kuklei

+0

Jeśli usuwasz z naprawdę dużych tabel InnoDB, możesz rozważyć zwiększenie 'innodb_buffer_pool_size'. To pierwsze zawiodło po 30 minutach wykonania dla mnie, więc zwiększyłem do 512 MB i udało mi się usunąć jakieś 13 milionów dodatkowych rekordów. Tabele, do których się przyłączyłem, to 44 miliony i 23 miliony rekordów, odpowiednio do ich kolejności w zapytaniu. –

Powiązane problemy