2013-02-22 21 views
10

Sto avendo problemi con la seguente query SQL e MySQLSQL SELECT DOVE NON IN dalla domanda stessa tabella

SELECT 
    id, cpid, label, cpdatetime 
FROM 
    mytable AS a 
WHERE 
    id NOT IN 
    (
    SELECT 
     id 
    FROM 
     mytable AS b 
    WHERE 
     a.label = b.label 
    AND 
     a.cpdatetime > b.cpdatetime 
) 
AND 
    label LIKE 'CB%' 
AND 
    cpid LIKE :cpid 
GROUP BY label 
ORDER BY cpdatetime ASC 

tavolo assomiglia a questo

1 | 170.1 | CB55 | 2013-01-01 00:00:01 
2 | 135.5 | CB55 | 2013-01-01 00:00:02 
3 | 135.6 | CB59 | 2013-01-01 00:00:03 
4 | 135.5 | CM43 | 2013-01-01 00:00:04 
5 | 135.5 | CB46 | 2013-01-01 00:00:05 
6 | 135.7 | CB46 | 2013-01-01 00:00:06 
7 | 170.2 | CB46 | 2013-01-01 00:00:07 

vorrei che la mia query per restituire

3 | 135.6 | CB59 
5 | 135.5 | CB46 

Modifica

0.123.

le etichette sono cani/gatti e cpids sono famiglia temporanea che mantiene i cani/gatti.

I cani/gatti si spostano da una famiglia all'altra.

ho bisogno di trovare i cani/gatti che erano in: userinput famiglia, ma solo se non erano in un'altra famiglia in precedenza

non può alterare il database e solo lavorare con i dati così come sono e Non sono io quello che ha scritto lo schema dell'applicazione/database.

+0

Si verificano errori? – Sir

+3

Non chiedere scusa - questa è una domanda ben scritta rispetto ad altre in cui si hanno informazioni sui premi usando le viti a testa piatta. –

+0

Spiacente, potresti spiegare perché non dovrebbe restituire la riga 1? È ': cpid = '13% '' forse? –

risposta

6

cercare di evitare le query sub correlate utilizzando LEFT JOIN:

SELECT a.id, a.cpid, a.label, a.cpdatetime 
FROM mytable AS a 
LEFT JOIN mytable AS b ON a.label = b.label AND a.cpdatetime > b.cpdatetime 
WHERE a.label LIKE 'CB%' AND a.cpid LIKE :cpid 
    AND b.label IS NULL 
GROUP BY a.label 
ORDER BY a.cpdatetime ASC 

Fiddle

Se la condizione di join non riesce, i campi della seconda alias tavolo b verrà impostato su NULL.

In alternativa, utilizzare una query sub non correlati:

SELECT a.id, a.cpid, a.label, a.cpdatetime 
FROM mytable AS a 
INNER JOIN (
    SELECT label, MIN(cpdatetime) AS cpdatetime 
    FROM mytable 
    WHERE label LIKE 'CB%' 
    GROUP BY label 
) AS b ON a.label = b.label AND a.cpdatetime = b.cpdatetime 
WHERE a.cpid LIKE '135%' 
ORDER BY a.cpdatetime 

In primo luogo, trovare il minimo cpdatetime per ogni etichetta e poi unirsi che con la prima tabella in cui si aggiunge la ulteriore cpid condizione.

1

Penso che questo sia davvero ciò che si vuole fare: selezionare gli ID che sono i primi ID per ciascuna etichetta, quindi selezionare tra quelli con 135 cpid e un'etichetta CB.

SELECT 
    A.id, cpid, A.label, cpdatetime 
FROM 
    mytable AS a inner join 
(select id, label from mytable 
    group by label 
    having min(cpdatetime)) as b 
on A.label=B.label and A.id=B.id 
WHERE 
    A.label LIKE 'CB%' 
AND 
    cpid LIKE '135%' 
GROUP BY A.label 
ORDER BY cpdatetime ASC; 

http://sqlfiddle.com/#!2/ccccf/16

+0

Non sarebbe 'avere min (cpdatetime)' sempre resa vera? –

+0

sia la tua soluzione e il lavoro di Jack, ma non sono sicuro di quale avrei dovuto contrassegnare come accettato. Capisco la risposta di Jack molto facilmente rispetto alla tua @joe quindi non ne sono proprio sicuro, sto ancora cercando di leggere altri input e scavare nella documentazione di MySQL – teuna

+0

Hm, suppongo che lo farebbe, non sarebbe vero? MySQL mi sta solo permettendo di barare con il gruppo e restituendo la riga con il numero più basso, non è vero, piuttosto che valutarla in maniera significativa ... sospiro – Joe

Problemi correlati