2017-01-14 3 views
1

I SELECT müssen *, wo verschiedene 'Rua' mit unterschiedlichen 'CP' im folgenden DB:alle Spalten aus verschiedenen zwei Spalten SELECT

id  Rua     Local   Conc  CP 
81143 dos moinhos   Rio Tinto  Gondomar
81142 dos Moinhos   Rio Tinto  Gondomar 4435 
81141 dos Moinhos   Rio Tinto  Gondomar 4435 

Mit der folgenden Abfrage, ich bin in der Lage, die beiden Säulen zu erhalten:

SELECT Rua, CP 
FROM Codigo 
GROUP BY Rua, CP 
HAVING COUNT(*) = 1 

Aber ich möchte alle Spalten. SELECT * gibt zurück "Die Spalte 'Codigo.id' ist in der Auswahlliste ungültig, da sie weder in einer Aggregatfunktion noch in der GROUP BY-Klausel enthalten ist." So

stieß ich auf diese Antwort: How do I (or can I) SELECT DISTINCT on multiple columns?

ich nicht für die akzeptierte Antwort ging, wie ich eine schnelle Abfrage benötigen (dies für AJAX Suchvorschläge verwendet werden). Ich habe die andere hochaufgelöste Antwort verwendet. Also, ich erstellt die folgende Abfrage:

SELECT * From Codigo 
WHERE (Rua,CP) IN (
    SELECT Rua, CP 
    FROM Codigo 
    GROUP BY Rua, CP 
    HAVING COUNT(*) = 1 
); 

Die gibt einen Ausdruck von nicht-Typ boolean in einem Kontext angegeben, wo eine Bedingung zu erwarten ist, in der Nähe ‚‘ Fehler. Warum erwartet man Rua nach WHERE Boolean zu sein? In der Antwort verwendeten sie saleprice, die nicht boolesch scheinen.

So ist meine Frage, wie kann ich alle Spalten einschließlich die Zeilen mit dem gleichen Rua und CP, aber die nur einmal (DISTINCT) wählen?

Antwort

1

SQL Server unterstützt nicht (a,b) in (val1,val2) Syntax

Verwenden EXISTS das Paar

SELECT * 
FROM Codigo C1 
WHERE EXISTS (SELECT 1 
       FROM Codigo C2 
       WHERE C1.Rua = C2.Rua 
         AND C1.CP = C2.CP 
       HAVING Count(*) = 1); 

oder COUNT() Over() Fensteraggregatfunktion verwenden, um zu überprüfen die Datensätze für jede Rua, CP Kombination zu zählen und die Gruppenfilter, die Zählung aufweist, Als 1 finden Sie eine Rua Zeile für jeden einzelnen CP.

SELECT * 
FROM (SELECT *, 
       Count(1)OVER(partition BY Rua, CP) AS cnt 
     FROM Codigo C1) A 
WHERE cnt = 1 

Dies wird mein bevorzugter Ansatz sein, da es viel effizienter ist als EXISTS mit den Optimierer zu scannen haben/versuchen, die Tabelle nur einmal

Wenn Sie nicht doppelte Datensätze wollen dann ROW_NUMBER() verwenden

SELECT * 
FROM (SELECT *, 
       Row_Number()OVER(partition BY Rua, CP Order by id) AS RN 
     FROM Codigo C1) A 
WHERE RN = 1 

Ich habe die doppelten Datensätze mit Id Spalte bestellt und den ersten Datensatz aus Duplikaten ausgewählt.

+0

Beide arbeiten . Der erste Vorschlag dauert 33 Sekunden, die Sekunden dauern 3 :) Warum so ein Unterschied? – Dillinger

+0

@Dillinger - Weil der Optimierer die Tabelle nur einmal in der zweiten Annäherung scannen/suchen muss –

+0

Ich denke, dass ich die Frage nicht richtig präsentierte. Ich möchte, dass die Zeilen mit der gleichen 'Rua' und' CP' ebenfalls enthalten sind, aber nur einmal. Damit bekomme ich nur Ergebnisse, die 'Rua' und' CP' nicht wiederholt haben. Wenn ich meine Frage bearbeite und behebe, werden Sie Ihre Antwort korrigieren? – Dillinger

2

mit Fenster-Funktion (Einzeltisch Lesen):

SELECT t.* 
FROM 
    (SELECT t.*, COUNT(1) OVER (partition BY Rua, CP) AS cnt FROM Codigo t 
) t 
WHERE cnt = 1; 

Mit VORHANDEN (Liest die Tabelle zweimal):

SELECT * 
FROM Codigo t1 
WHERE EXISTS 
    (SELECT 1 
    FROM Codigo t2 
    WHERE t1.Rua = t2.Rua 
    AND t1.CP  = t2.CP 
    GROUP BY Rua, CP 
    HAVING COUNT(*) = 1 
); 

JOIN (zweimal wieder):

SELECT C1.* 
FROM Codigo C1 
INNER JOIN 
    (SELECT Rua, CP FROM Codigo C2 GROUP BY Rua, CP HAVING COUNT(*) = 1 
) C2 
ON C1.Rua = C2.Rua 
AND C1.CP = C2.CP; 
+0

'GROUP BY' in' Exists' Methode wird nicht benötigt –

Verwandte Themen