2015-11-25 22 views
5

Siamo spiacenti in anticipo per questa domanda se la soluzione dovrebbe essere ovvia. Ho cercato ma non ho ancora trovato una soluzione.Query conteggio SQL con join sulla stessa tabella

Ho una tabella Ordini che include 2 colonne: CustID e ProductBrand. ProductBrand è la marca dell'articolo ordinato, ad es. Sony, HP, Dell, ecc.

Desidero ottenere l'elenco dei clienti che hanno ordinato almeno 10 articoli con ProductBrand = Sony ma meno di 5 elementi con ProductBrand = HP.

Posso farlo con qualcosa in questo senso?

SELECT o1.CustID 
FROM Orders o1 HAVING COUNT(o1.ProductBrand="Sony") >= 10 
INNER JOIN Orders o2 ON o1.CustID = o2.CustID 
HAVING COUNT(o2.ProductBrand="HP") < 5; 
+0

qual è stato il risultato della query? .. – tharif

+0

La query che ho fornito nella descrizione viene effettivamente respinta dal parser SQL. L'ho appena fornito per fornire alcuni dettagli su ciò che stavo cercando di fare. Scusa se non l'ho chiarito. – Point

risposta

5

Si potrebbe fare questo senza un self-join, solo l'aggregazione:

select o.custid 
from orders o 
group by o.custid 
having sum(case when o.ProductBrand = 'Sony' then 1 else 0 end) >= 10 and 
     sum(case when o.ProductBrand = 'HP' then 1 else 0 end) < 5; 

In MySQL, è possibile semplificare questo rimuovendo il case:

select o.custid 
from orders o 
group by o.custid 
having sum(o.ProductBrand = 'Sony') >= 10 and 
     sum(o.ProductBrand = 'HP') < 5; 
+0

Ha funzionato! Grazie mille. Ora che lo vedo, sembra semplice e ovvio, ma non avrei saputo nulla senza un indizio. Grazie per avere condiviso le tue conoscenze. – Point

0

Setup violino

CREATE TABLE ORDERS (cust INT, brand VARCHAR(100)) 

INSERT INTO ORDERS VALUES (1, 'Sony') 
INSERT INTO ORDERS VALUES (1, 'Sony') 
INSERT INTO ORDERS VALUES (1, 'Sony') 
INSERT INTO ORDERS VALUES (1, 'Hp') 
INSERT INTO ORDERS VALUES (1, 'Hp') 
INSERT INTO ORDERS VALUES (2, 'Sony') 
INSERT INTO ORDERS VALUES (2, 'Sony') 
INSERT INTO ORDERS VALUES (2, 'Hp') 
INSERT INTO ORDERS VALUES (2, 'Hp') 
INSERT INTO ORDERS VALUES (2, 'Hp') 
INSERT INTO ORDERS VALUES (2, 'Hp') 
INSERT INTO ORDERS VALUES (3, 'Sony') 
INSERT INTO ORDERS VALUES (3, 'Sony') 
INSERT INTO ORDERS VALUES (3, 'Sony') 
INSERT INTO ORDERS VALUES (3, 'Hp') 
INSERT INTO ORDERS VALUES (3, 'Hp') 

Richiesta

Metodo 1

select 
    sony.custId 
from 
    (select cust as custId, Brand, count(*) as count 
    from orders 
    where Brand = 'Sony' 
    group by cust, brand) Sony 
     inner join 
    (select cust as custId, Brand, count(*) as count 
     from orders 
     where Brand = 'Hp' 
     group by cust, brand) Hp 
      on sony.custId = hp.CustId 
Where 
    sony.count > 2 and 
    hp.count < 5 

Questo è un bene per voi capire relazione. Ecco un altro modo

Metodo 2

select cust 
from orders 
group by cust, brand 
having count(case brand when 'Sony' then 'x' end) > 2 and 
     count(case brand when 'Hp' then 'x' end) < 5 

Il tempo è circa lo stesso - sicuro che variano in base alla quantità di dati, indici, ecc utilizzare SQL violino per controllare piano di esecuzione. Sembra che nel primo metodo accadano altre cose. Ma non significa che quando si utilizza in produzione, sarà molto peggio.

+0

Che strumento utile! Stavo cercando qualcosa di simile: scoprire Fiddle era, di per sé, degno di questo post. Con il tuo metodo 1 ora vedo come deve essere la sintassi del join interno: ho pensato che ci fosse un modo per specificare le query separate e poi unirle a dei confronti di conteggio, ma non abbiamo trovato esempi per problemi simili ai miei. T.S., ti ringrazio per la tua generosità nel prendere tempo per fornire una soluzione - spero di poter fare lo stesso per qualcun altro come hai fatto per me. – Point

Problemi correlati