2015-05-28 17 views
8

Ho una tabella di persone che hanno un nome, posizione (dove vivono) e un parent_id (i genitori sono memorizzati su un'altra tabella). Così, per esempio:Conta record SQL in base alla proprietà di pari livello

name | location | parent_id 
--------+-----------+----------- 
Joe  | Chicago | 12 
Sammy | Chicago | 13 
Bob  | SF  | 13 
Jim  | New York | 13 
Jane | Chicago | 14 
Dave | Portland | 14 
Al  | Chicago | 15 
Monica | Boston | 15 
Debbie | New York | 15 
Bill | Chicago | 16 
Bruce | New York | 16 

ho bisogno di contare quante persone vivono a Chicago e hanno fratelli (condividere una parent_id) che vivono a New York. Così, per l'esempio precedente, il conteggio sarebbe 3.

name | location | parent_id 
--------+-----------+----------- 
Joe  | Chicago | 12 
Sammy | Chicago | 13 * sibling Jim lives in New York 
Bob  | SF  | 13 
Jim  | New York | 13 
Jane | Chicago | 14 
Dave | Portland | 14 
Al  | Chicago | 15 * sibling Debbie lives in New York 
Monica | Boston | 15 
Debbie | New York | 15 
Bill | Chicago | 16 * sibling Bruce lives in New York 
Bruce | New York | 16 

qualcuno può aiutarmi a scrivere il codice SQL per interrogare questo conteggio?

risposta

1

La query correlata è un modo molto carino di andare ed è molto efficiente. Evitare l'uso di distinti in quanto è un'operazione costosa. Raggruppa è una bella alternativa all'uso di distinti. Comprendere i dati e strutturare la query di conseguenza. Ecco un'altra opzione ottimizzata per il motore ...

select count(*) 
from (select * from #t where Location = 'Chicago') ch 
inner join (select * from #t where Location = 'New York') ny on ch.ParentID = ny.ParentID 
+0

Quelle non sono sottoquery correlate, sono solo sottoquery e la tua risposta soffre dello stesso problema che inizialmente faceva PD1ce; conta le persone a Chicago con N fratelli a New York N volte. – Uueerdo

1

Forse provarlo?

SELECT Count(*) 
FROM table table1 
WHERE table1.location= 'Chicago' 
     AND EXISTS (SELECT * FROM table table2 
        WHERE table1.parent_id= table2.parent_id 
          AND table2.location= 'New York') 
3

Sembra che la risposta di Minh funzioni alla grande, ma qui c'è un altro esempio che utilizza un Self Join.

SELECT Count(DISTINCT a.child_id) 
FROM people a 
    JOIN people b ON a.parent_id = b.parent_id 
WHERE a.location = 'Chicago' AND b.location = 'New York' 

dovrebbe produrre "3" solo per la tabella sopra elencati.

MODIFICA: aggiunto un DISTINCT a.parent_id basato sul suggerimento di Lithis.

EDIT2: Come notato da Uueerdo, un child_id o una sorta di ID univoco potrebbe davvero aiutare nel caso di 2 fratelli che vivono a Chicago e 1 fratello che vive a New York. Ho modificato la query originale per riflettere questo.

Poiché questa non è veramente una "risposta" alla tua domanda, perché non esiste un tale child_id, vorrei rimandare alla risposta di Uueerdo, mi dispiace!

+0

Non ho eseguito la query, ma sembra che conterebbe una singola persona due volte se hanno due fratelli diversi a New York. Forse l'aggiunta di 'GROUP BY a.id' o l'uso di' COUNT (DISTINCT a.id) 'impedirebbe questo. – Lithis

+0

Hai ragione Lithis, non l'ho capito. Modificherò il mio post. – PD1ce

+0

Hai davvero bisogno di un "id figlio", se due persone a Chicago hanno lo stesso genitore, verranno contate una sola volta. In realtà, 'COUNT (DISTINCT a. *)' Potrebbe funzionare? – Uueerdo

1
SELECT COUNT(*) 
FROM `people` AS p1 
WHERE p1.`location` = 'Chicago' 
     AND p1.parent_id IN (
     SELECT DISTINCT parent_id 
     FROM `people` AS p2 
     WHERE p2.`location` = 'New York' 
     ) 
; 

Utilizzando Minh come base, questo dovrebbe essere abbastanza veloce; poiché la sottoquery non è più "correlata", non dovrebbe rischiare la possibilità che sia eseguita ripetutamente, una volta per ogni riga in people.

Problemi correlati