2015-04-22 11 views
7

Ho quattro tavole (in [] sono colonne):mysql selezionare/eliminare utilizzando unire più di quattro tavoli

users [id]

products [id]

productRatings [id,value,user,product]

comments [id,product,user]

lo farei come selezionare/ed eliminare definitivamente productRatings dove non ci sono commenti associati da parte di stesso utente per quel prodotto. Cioè, se l'utente ha valutato il prodotto ma non ha commentato, quella valutazione dovrebbe essere cancellata.

credo che potrei ottenere che utilizzando due query, in primo luogo:

SELECT user, product FROM productRatings 

e poi per ogni riga:

SELECT COUNT(*) FROM comments WHERE product=productRatings.product AND user=productRatings.user 

e poi qualcosa come

if $queryAbove==0 : DELETE FROM productRatings WHERE id=productRatings.id 

lo farei piace risolvere questo tramite JOIN e imparare di più con l'esempio piuttosto che scavare attraverso tutorial JOIN.

risposta

4

è necessario solo il productratings e commenti tavolo - le seguenti opere:

delete pr 
from productratings pr 
left join comments c 
    on pr.userid = c.userid 
    and pr.productid = c.productid 
where c.productid is null 

E c'è una demo qui: http://sqlfiddle.com/#!9/89575/1

+0

questo lo ha fatto, grazie, questa unione è davvero semplice quando sai cosa stai facendo – dbr

0
DELETE FROM productRatings WHERE id IN (SELECT pr.id FROM productRatings pr 
     LEFT JOIN comments c on c.product = pr.product 
     WHERE c.user = pr.user 
     AND pr.comment IS NULL) 
+0

Questo non realizzare quello che l'OP ha chiesto. Vuole eliminare una valutazione del prodotto in cui nessun commento esiste dall'utente che ha creato la valutazione del prodotto. Non tenerlo se QUALUNQUE commento esiste –

+0

@pala_ Grazie! Dovevo digiunare – smiggle

+0

questo probabilmente fallirebbe in quanto 'WHERE id =' con una selezione annidata che fornirà più di un risultato. con l'uso di 'IS NULL' dovrebbe essere' IN' invece di '=' –

1

Dovreste essere in grado di aderire solo i campi nella query e quindi verificare se il commento è vuoto, in questo modo ...

DELETE FROM `productRatings` 
JOIN `comments` ON (`productRatings`.`product` = `comments`.`product`) 
WHERE `comments`.`comment_field` IS NULL 
AND `productRatings`.`user_id` = ?; 

La IS NULL potrebbero dover essere sostituito con = '' a seconda del motore di database che si utilizza.

Ricordarsi di eseguire prima il test su un'istanza di test del DB!

+0

Non sono sicuro che sia necessario unirsi alla tabella utente in quanto entrambi i commenti e le tabelle delle valutazioni hanno identificativi utente. –

+0

Vero, modifica la risposta, grazie –

+0

Penso che questo fallirà perché è un join e non hai specificato da quale tabella cancellare. –

2
DELETE FROM `productRatings` WHERE productRatings.id NOT IN (
SELECT productRatings.id FROM `productRatings` JOIN `comments` ON productRatings.user = comments.user AND productRatings.product = comments.product) 

mi piacerebbe fare copie delle tabelle in questione e verificare che le opere di cui sopra sui tavoli di prova prima di usare questo sulle vostre tavole di produzione.

Fondamentalmente, la selezione annidata restituirà tutti gli ID di prodotti ID che l'utente che ha scritto la valutazione ha anche fatto un commento. Usando NOT IN, eliminerà tutte le valutazioni che l'utente che ha effettuato la valutazione non ha anche commentato.

Come pala_ evidenziato nei commenti seguenti, poiché questo metodo utilizza sql annidato, funzionerà in modo peggiore di un metodo che utilizza solo join su tabelle più grandi.

+0

per tabelle di grandi dimensioni, questo si comporta peggio di una versione che utilizza solo join. –

+0

@pala_ sì, lo aggiungerò alla mia risposta. La tua risposta sembra superiore in quanto non usa sql annidato. –