2013-04-12 18 views
20

Si supponga che ho due tabelle:Selezionare righe che corrispondono a tutti gli elementi di un elenco

cars - elenco delle vetture

carname | modelnumber | ... 

passedtest - contiene tutti i test che una macchina passava:

id | carname | testtype | date | ... 
1 | carA | A  | 2000 | 
2 | carB | C  | 2000 | 
3 | carC | D  | 2001 | 
4 | carA | C  | 2002 | 

Ora, come posso selezionare un'auto dalla tabella passedtest che ha superato tutti i test (A, B, C, D)?

Ho provato la dichiarazione IN ma corrisponde anche alle auto che superano anche un solo test. Sto cercando una dichiarazione per corrispondere a tutti i valori in un elenco su tutte le righe.

risposta

29

Che ne dici di questo?

SELECT carname 
FROM PassedTest 
GROUP BY carname 
HAVING COUNT(DISTINCT testtype) = 4 

È possibile anche usarlo come una dichiarazione interna per prendere informazioni dal tavolo cars:

SELECT * 
FROM cars 
WHERE carname IN (
    SELECT carname 
    FROM PassedTest 
    GROUP BY carname 
    HAVING COUNT(DISTINCT testtype) = 4 
) 
+0

grazie ma l'uscita che ho è ripetuto credo perché per creare automobili tavolo ho usato INNER JOIN – user1229351

+0

Tuttavia, questo non funziona con caratteri jolly, poiché in tal caso il conteggio esplicita non può essere stabilito –

20

Questo tipo di problema si chiama Relational Division.

SELECT a.* 
FROM Cars a 
     INNER JOIN 
     (
      SELECT CarName 
      FROM PassedTest 
      WHERE testType IN ('A', 'B', 'C', 'D') 
      GROUP BY CarName 
      HAVING COUNT(*) = 4 
     ) b ON a.CarName = b.CarName 

se un vincolo UNIQUE non è stato far rispettare il TestType per ogni CarName sul tavolo PassedTest una parola chiave DISTINCT è richiesto COUNT() così sarà solo contare valori unici.

SELECT a.* 
FROM Cars a 
     INNER JOIN 
     (
      SELECT CarName 
      FROM PassedTest 
      WHERE testType IN ('A', 'B', 'C', 'D') 
      GROUP BY CarName 
      HAVING COUNT(DISTINCT TestType) = 4 
     ) b ON a.CarName = b.CarName 

ma se siete interessati solo sulla CARNAME allora non c'è bisogno di unire le tabelle. Interrogare sul tavolo PassedTest soddisferà le tue esigenze.

SELECT CarName 
FROM PassedTest 
WHERE testType IN ('A', 'B', 'C', 'D') 
GROUP BY CarName 
HAVING COUNT(*) = 4 
0

si desidera eseguire la divisione relazionale, un'operazione che non è implementata in SQL. Ecco un esempio in cui abbiamo un prodotto-fornitore tavolo e un -prodotti richiesti tavolo:

CREATE TABLE product_supplier (
    product_id int NOT NULL, 
    supplier_id int NOT NULL, 
    UNIQUE (product_id, supplier_id) 
); 
INSERT INTO product_supplier (product_id, supplier_id) VALUES 
(1, 1), 
(2, 1), 
(3, 1), 
(1, 2), 
(2, 2), 
(3, 2), 
(4, 2), 
(2, 3), 
(3, 3), 
(4, 3); 

CREATE TABLE reqd (
    product_id int NOT NULL, 
    UNIQUE (product_id) 
); 
INSERT INTO reqd (product_id) VALUES 
(1), 
(2), 
(3); 

... e vogliamo trovare tutti i fornitori che forniscono tutti i prodotti necessari e forse altri. Il risultato nell'esempio sopra sarebbe il fornitore 1 e 2.

La soluzione in avanti più retta è questo:

SELECT product_supplier.supplier_id 
FROM product_supplier 
LEFT JOIN reqd ON product_supplier.product_id = reqd.product_id 
GROUP BY product_supplier.supplier_id 
HAVING COUNT(reqd.product_id) = (SELECT COUNT(*) FROM reqd); 
+-------------+ 
| supplier_id | 
+-------------+ 
|   1 | 
|   2 | 
+-------------+ 

E se vogliamo trovare tutti i fornitori che forniscono tutti i prodotti necessari e non altre (divisione esatto/senza resto) quindi aggiungere una condizione più a quanto sopra:

SELECT product_supplier.supplier_id 
FROM product_supplier 
LEFT JOIN reqd ON product_supplier.product_id = reqd.product_id 
GROUP BY product_supplier.supplier_id 
HAVING COUNT(reqd.product_id) = (SELECT COUNT(*) FROM reqd) 
AND COUNT(product_supplier.product_id) = (SELECT COUNT(*) FROM reqd); 
+-------------+ 
| supplier_id | 
+-------------+ 
|   1 | 
+-------------+ 

Una soluzione alternativa consiste nel riformulare il problema: selezionare s uppliers dove non esiste un prodotto richiesto che non esiste nei prodotti forniti dal fornitore. Hmmm:

SELECT DISTINCT supplier_id 
FROM product_supplier AS ps1 
WHERE NOT EXISTS (
    SELECT * 
    FROM reqd 
    WHERE NOT EXISTS (
     SELECT * 
     FROM product_supplier AS ps2 
     WHERE ps1.supplier_id = ps2.supplier_id AND ps2.product_id = reqd.product_id 
    ) 
); 
+-------------+ 
| supplier_id | 
+-------------+ 
|   1 | 
|   2 | 
+-------------+ 
Problemi correlati