2017-02-01 2 views
2

Es mit Spalten einer Tabelle T ist n00, n01, n01, ..., n99, alle ganzen Zahlen.alle Zeilen auswählen, in dem Spaltenwerte sind einzigartig

Ich brauche alle Zeilen aus dieser Tabelle zu wählen, in der n00 ... n99 Werte innerhalb jeder Zeile eindeutig sind.

Beispiel für kleinere Anzahl von Spalten:

columns: n0, n1, n2 
row 1: 10, 20, 30 
row 2: 34, 45, 56 
row 3: 12, 13, 12 
row 4: 31, 65, 90 

ich brauche die SELECT-Anweisung Zeilen zurückgeben 1, 2 und 4, aber nicht mehr als 3 (Reihe 3 enthält nicht eindeutigen Wert von 12 es so herauszufiltern).

Effektiv muss ich dies implementieren:

select * 
from t 
where 
     n00 <> n01 and n00 <> n02 and ... and n00 <> n99 
    and n01 <> n02 and n01 <> n03 and ... and n01 <> n99 
    and n02 <> n03 and n02 <> n04 and ... and n02 <> n99 
    ... 
    and n97 <> n98 and n97 <> n99 
    and n98 <> n99 

... aber mit "intelligenter" WHERE-Block.

Irgendwelche Hinweise begrüßen.

Antwort

2

Sie UNPIVOT auch verwenden können:

DECLARE @t TABLE(n0 int, n1 int, n2 int); 
INSERT INTO @t VALUES (10, 20, 30), (34, 45, 56), (12, 13, 12), (31, 65, 90); 

WITH cteRows AS(
    SELECT ROW_NUMBER() OVER (ORDER BY n0, n1, n2) rn, * 
      FROM @t 
), 
cteUP AS(
    SELECT rn, rn_val 
    FROM cteRows 
    UNPIVOT(
    rn_val FOR rn_vals IN(n0, n1, n2) 
) up 
), 
cteFilter AS(
    SELECT rn, rn_val, count(*) anz 
    FROM cteUP 
    GROUP BY rn, rn_val 
    HAVING count(*) > 1 
) 
SELECT * 
    FROM cteRows 
    WHERE rn NOT IN (SELECT rn FROM cteFilter) 
+1

Ich bevorzuge Ihre Lösung gegenüber John's, da es keine internen Konvertierungen zu/von XML beinhaltet. Beide liefern jedoch korrekte Ergebnisse. –

2

Ein dynamischer Ansatz CROSS APPLY und ein wenig XML. Ich sollte hinzufügen, UNPIVOT wäre leistungsfähiger, aber die Leistung dieses Ansatzes ist sehr respektabel, und Sie haben nicht alle Felder zu identifizieren.

Sie werden bemerken, ich ein ID-Feld hinzugefügt. Kann aus dem CROSS APPLY C entfernt werden, wenn es nicht existiert. Ich habe die ID hinzugefügt, um zu demonstrieren, dass zusätzliche Felder von der Logik ausgeschlossen werden können.

Declare @YourTable table (id int,n0 int, n1 int, n2 int) 
Insert Into @YourTable values 
(1,10, 20, 30), 
(2,34, 45, 56), 
(3,12, 13, 12), 
(4,31, 65, 90) 

Select A.* 
From @YourTable A 
Cross Apply (Select XMLData=cast((Select A.* For XML Raw) as xml)) B 
Cross Apply (
       Select Cnt=count(*),Uniq=count(Distinct Value) 
       From (
         Select ID  = r.value('@id','int')          -- case sensitive 
           ,Item = attr.value('local-name(.)','varchar(100)') 
           ,Value = attr.value('.','varchar(max)') 
         From B.XMLData.nodes('/row') as A(r) 
         Cross Apply A.r.nodes('./@*') AS B(attr) 
         Where attr.value('local-name(.)','varchar(100)') not in ('id','excludeotherfields') -- case sensitive 
        ) U 
      ) C 
Where Cnt=Uniq 

Returns

id n0 n1 n2 
1 10 20 30 
2 34 45 56 
4 31 65 90 

Wenn es mit der Visualisierung hilft, erzeugt der XML-Teil der folgenden

enter image description here

+1

John, ich verstehe deine Antwort nicht, aber es liefert korrekte Ergebnisse. Ich muss jetzt zur SQL Crèche gehen. Ich wähle die Antwort von Tyron78 ​​gegenüber Ihrer, da keine XML-Konvertierung erforderlich ist. Trotzdem bin ich erstaunt. –

+2

@xpil Welche Antwort immer am besten für Sie funktioniert. Behalte den XML-Teil in deiner Gesäßtasche. Ich fand es nützlich für die dynamische Umwandlung von Daten in eine EAV (Entity Attribute Value) -Struktur. –

Verwandte Themen