2010-02-08 2 views
5

Wenn ich eine Tabelle wie folgt habe:Wie erhält man einen eindeutigen Satz von Zeilen aus SQL, wo die Eindeutigkeit durch 2 Spalten definiert ist?

ID | Name | Kategorie | Eltern | URL | LastModified

Wenn zwei Zeilen denselben Namen und dasselbe Elternelement haben, sind sie nicht eindeutig. Wie bekomme ich in diesem Fall die eindeutige Menge von Zeilen (aber mehr als die Spalten, die sie eindeutig machen)?

So, für weitere Details: Dies ist eine Unternehmens-Stichwörter Tabelle, wo Schlüsselwörter nach Kategorie organisiert sind. Jedes Keyword kann nur eine Kategorie haben. Jedes Schlüsselwort kann untergeordnete Schlüsselwörter haben. Wenn also parent = 0 oder NULL ist, handelt es sich um ein root-Schlüsselwort. Wenn Schlüsselwörter in einer Kategorie denselben Namen und denselben übergeordneten Namen haben, sind sie nicht eindeutig (unabhängig von den anderen Spalten). Wenn zwei Schlüsselwörter denselben Namen und dieselbe Kategorie haben und parent = 0 oder NULL, sind sie nicht eindeutig. Wenn es Duplikate gibt, möchte ich nur die erste. Der Grund ist, dass ich diese in ein System setze, das einem Keyword nicht erlaubt, zwei Kinder mit demselben Namen zu haben.

Ich würde auch gerne sehen, welche Zeilen Duplikate sind, um zu sehen, was mir die Probleme verursacht!

Danke eine Million bis jetzt für ausgezeichnete Antworten. Ich bin offensichtlich kein SQL-Typ ... :(

+0

Was willst du bekommen? Die Kategorien für einen Namen/Eltern? –

+0

Fehlende Angabe: Wenn zwei Zeilen den gleichen Eltern- und Namen haben, möchten Sie nur eine oder keine von ihnen zurückgeben. Wenn der ehemalige, welcher? –

+0

Fehlende Angabe: Was ist, wenn zwei Zeilen den gleichen Namen haben, aber beide über NULL verfügen? Bedeutet das, dass sie nicht einzigartig sind? –

Antwort

4

Diese Abfrage findet alle Zeilen, in denen keine andere Zeile den gleichen Namen und den gleichen Namen hat. Wenn für zwei Zeilen parent auf NULL gesetzt ist, wird davon ausgegangen, dass diese Zeilen nicht das gleiche übergeordnete Element haben.

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 Das würde auch funktionieren – Andomar

+0

Ich bin überrascht, dass Sie diese Antwort akzeptieren, da sie die zusätzliche Spezifikation, die Sie hinzugefügt haben, nicht erfüllt. "Wenn die Zeilen das gleiche Elternteil und denselben Namen haben, geben Sie beides zurück." Ich denke, dass Andomars erster Vorschlag es tut. –

7

Es hängt davon ab, was Sie mit nicht eindeutigen Zeilen tun wollen. Wenn Sie sie nicht in der Ergebnismenge haben möchten, könnten Sie Gruppe verwenden und haben:

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

Sie müssen den Max (Kategorie), weil Sie nicht nach dieser Spalte Gruppierung, auch wenn es nur eine Zeile pro Namen und Eltern sein.

Wenn aber, Sie wollen nicht schließen eindeutige Zeilen im Ergebnis, ähnlich wie:

select distinct Name, Parent, Category from Table 

mit der Ausnahme, dass zwei Zeilen mit demselben Namen und Parent aber unterschiedlicher Category nur eine einzelne Zeile zurückgeben. In diesem Fall müssen Sie entscheiden, was für eine Kategorie angezeigt werden soll, da mehr als eine Zeile auf eine Zeile reduziert wird. Du könntest immer noch Max (Kategorie) oder Min (Kategorie) verwenden und nach Gruppen gruppieren, aber lass das nicht.

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

Das wird nur eine Zeile zurückgeben, aber die "max" -Kategorie für einen bestimmten Namen/Elternteil. –

+0

Was ist das, was er will, alle eindeutigen Zeilen (basierend auf Name und Eltern) und die Kategorie jeder dieser Zeilen gehört. –

+0

Darf es nicht mehr als eine Kategorie für einen bestimmten Namen/Elternteil enthalten? Wenn ja, sollten mehr als eine Kategorie zurückgegeben werden. (Schätze, wir müssten das aus dem OP herausfinden.) –

2

könnten Sie verwenden die Funktion row_number nach Namen und Eltern zu partitionieren, wie:

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 

Wenn Sie suchen nur Zeilen auszuwählen, die einzigartig sind, in dem Sinne, dass keine anderen Zeilen mit die gleichen Namen und Eltern vorhanden ist, versuchen:

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

+1 für den Zeilennummervorschlag. Ihre 'order by' ist ziemlich nutzlos - es wäre sinnvoller, wenn Sie nach einer der Spalten suchen, die sich nicht in der Partition befinden, zum Beispiel id. Ich habe eine klärende Frage dazu als Kommentar zu der Frage gestellt, aber noch keine Antwort erhalten, daher ist nicht klar, welche Reihe er in dieser Situation haben möchte. –

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) 

laufen kann langsam je nach Tischgröße

+0

+1 Oder versuchen Sie 'Select *' :) – Andomar

Verwandte Themen