2010-02-08 10 views
5

Se ho una tabella come segue:Come ottenere un set univoco di righe da SQL dove l'univocità è definita da 2 colonne?

ID | Nome | Categoria | Parent | URL | LastModified

Se due righe hanno lo stesso nome e padre, non sono univoci. Come posso ottenere il set univoco di righe in questo caso (ma restituire più delle colonne che le rendono univoche)?

Quindi, per ulteriori dettagli: Questa è una tabella di parole chiave aziendali, in cui le parole chiave sono organizzate per categoria. Ogni parola chiave può avere solo una categoria. Ogni parola chiave può avere parole chiave figlio, quindi se genitore = 0 o NULL, è una parola chiave root. Se le parole chiave hanno lo stesso nome e genitore in una categoria, non sono uniche (indipendentemente dalle altre colonne). Se due parole chiave hanno lo stesso nome e categoria e genitore = 0 o NULL, non sono univoci. Se ci sono duplicati, allora voglio solo il primo. Il motivo è che sto inserendo questi in un sistema che non permetterà a una parola chiave di avere due figli con lo stesso nome.

Vorrei anche vedere quali file sono duplicati per vedere che cosa mi sta causando il problema!

Grazie mille per le risposte eccellenti. Ovviamente non sono un ragazzo di SQL ... :(

+0

Cosa stai cercando di ottenere? Le categorie per un nome/genitore? –

+0

Specifica mancante: se due righe hanno lo stesso nome principale e lo stesso nome, si desidera restituire solo uno di essi o nessuno dei due. Se il primo, quale? –

+0

Specifiche mancanti: cosa succede se due righe hanno lo stesso nome, ma entrambe hanno il padre impostato su NULL? Questo significa che non sono unici? –

risposta

4

Questa query trova tutte le righe dove nessun altra riga contiene lo stesso nome e genitore. Se due righe hanno il padre impostato su NULL, non si considera che queste righe abbiano lo stesso padre.

SELECT T1.* 
FROM Table1 T1 
LEFT JOIN Table1 T2 
ON T1.ID != T2.ID AND T1.Name = T2.Name AND T1.Parent = T2.Parent 
WHERE T2.ID IS NULL 
+0

+1 Funzionerebbe anche – Andomar

+0

Sono sorpreso che tu accetti questa risposta in quanto non soddisfa le specifiche aggiuntive che hai aggiunto 'Se le righe hanno lo stesso nome e il genitore, restituiscile'. Penso che il primo suggerimento di Andomar lo faccia comunque. –

7

Dipende da ciò che si desidera fare con le righe non univoche. Se non si desidera che siano nel set di risultati, è possibile utilizzare il gruppo per:

select Name, Parent, Max(Category) 
from Table 
group by Name, Parent 
having count(*) = 1 

è necessario il Max (Categoria) perché non si raggruppamento per quella colonna, anche se ci sarà una sola riga per nome e genitore.

Se, però, si desidera includere non- righe univoche nel risultato, simile a:

select distinct Name, Parent, Category from Table 

tranne per il fatto che due righe con lo stesso nome e padre ma di categoria diversa restituiscono solo una riga. In tal caso è necessario decidere cosa mostrare per Categoria, poiché più di una riga sarà ridotta a uno. Potresti comunque utilizzare Max (Categoria) o Min (Categoria) e raggruppare per, ma lasciare fuori l'avere.

select Name, Parent, Max(Category) 
from Table 
group by Name, Parent 
+0

Questo restituirà solo una riga, tuttavia, la categoria "max" per un determinato Nome/Parent. –

+0

Che è ciò che vuole, tutte le righe univoche (basate sul nome e sul genitore) e la categoria a cui appartiene ciascuna di queste righe. –

+0

Potrebbe non esserci più di una categoria inclusa per un determinato Nome/Parent? In tal caso, è necessario restituire più di una categoria. (Immagino che avremmo bisogno di scoprirlo dall'OP.) –

2

è possibile utilizzare la funzione row_number partizionare per nome e Parent, come:

select * 
from (
    select 
     row_number() over (partition by Name, Parent 
          order by Name, Parent) as rn 
    , * 
    from YourTable 
) sub 
where rn = 1 -- Only first row for a name/parent combination 

Se stai cercando di selezionare solo le righe che sono unici, nel senso che nessun altro le righe con lo stesso nome e genitore esistono, provare:

select * 
from YourTable a 
where (
    select count(*) 
    from YourTable b 
    where a.Name = b.Name 
    and a.Parent = b.Parent 
) = 1 
+0

+1 per il suggerimento numero_riga. Il tuo ordine da è piuttosto inutile: avrebbe più senso ordinare da una delle colonne non nella partizione, ad esempio l'id. Ho fatto una domanda di chiarimento su questo come commento alla domanda, ma non ho ancora ricevuto una risposta, quindi non è chiaro quale riga desideri in questa situazione. –

1
select x,y,z 
from tablename t1 
where not exists (select 1 from tablename t2 where t2.name = t1.name and t1.parent = t2.parent and t2.id <> t1.id) 

può funzionare lento a seconda delle dimensioni tavolo

+0

+1 Oppure prova 'seleziona *' :) – Andomar

Problemi correlati