it-swarm.com.de

Wie werden nur die ersten Zeilen für jeden eindeutigen Wert einer Spalte ausgewählt?

Nehmen wir an, ich habe eine Tabelle mit Kundenadressen:

CName           |   AddressLine
-------------------------------
John Smith      | 123 Nowheresville
Jane Doe        | 456 Evergreen Terrace
John Smith      | 999 Somewhereelse
Joe Bloggs      | 1 Second Ave

In der Tabelle kann ein Kunde wie John Smith mehrere Adressen haben. Ich brauche die Auswahlabfrage für diese Tabelle, um nur die erste Zeile zurückzugeben, in der Duplikate in 'CName' gefunden wurden. Für diese Tabelle sollten alle Zeilen mit Ausnahme der 3. (oder 1.) zurückgegeben werden (jede dieser beiden Adressen ist in Ordnung, aber es kann nur eine zurückgegeben werden.) Gibt es ein Schlüsselwort, das ich der SELECT-Abfrage hinzufügen kann, um basierend darauf zu filtern, ob Server hat den Spaltenwert schon gesehen?

68
nuit9

Eine sehr einfache Antwort, wenn Sie sagen, es ist Ihnen egal, welche Adresse verwendet wird.

SELECT
    CName, MIN(AddressLine)
FROM
    MyTable
GROUP BY
    CName

Wenn Sie die erste entsprechend einer "eingefügten" Spalte haben möchten, ist es eine andere Abfrage

SELECT
    M.CName, M.AddressLine,
FROM
    (
    SELECT
        CName, MIN(Inserted) AS First
    FROM
        MyTable
    GROUP BY
        CName
    ) foo
    JOIN
    MyTable M ON foo.CName = M.CName AND foo.First = M.Inserted
105
gbn

In SQL 2k5 + können Sie Folgendes tun:

;with cte as (
  select CName, AddressLine,
  rank() over (partition by CName order by AddressLine) as [r]
  from MyTable
)
select CName, AddressLine
from cte
where [r] = 1
21
Ben Thul

Sie können row_number() verwenden, um die Zeilennummer der Zeile abzurufen. Es verwendet den Befehl over - die partition by-Klausel gibt an, wann die Nummerierung erneut gestartet werden soll, und der order by legt fest, worauf die Zeilennummer angeordnet werden soll. Selbst wenn Sie am Ende Ihrer Abfrage einen order by hinzugefügt haben, bleibt die Reihenfolge im Befehl over bei der Nummerierung erhalten.

select *
from mytable
where row_number() over(partition by Name order by AddressLine) = 1
9
Rizzi Frank

Sie können die row_numer() over(partition by ...)-Syntax wie folgt verwenden:

select * from
(
select *
, ROW_NUMBER() OVER(PARTITION BY CName ORDER BY AddressLine) AS row
from myTable
) as a
where row = 1

Dies bewirkt, dass eine Spalte mit dem Namen row erstellt wird. Dies ist ein Zähler, der jedes Mal inkrementiert wird, wenn dieselbe Variable CName angezeigt wird, und diese Vorkommen mit AddressLine indiziert. Durch Auferlegen von where row = 1 kann man die CName auswählen, deren AddressLine alphabetisch zuerst kommt. Wenn der order bydesc wäre, würde er die CName auswählen, deren AddressLine als letztes alphabetisch kommt.

4
FatihAkici

Dadurch erhalten Sie eine Zeile jeder doppelten Zeile. Es gibt auch die Bit-Typ-Spalten, und es funktioniert zumindest in MS SQL Server. 

(select cname, address 
from (
  select cname,address, rn=row_number() over (partition by cname order by cname) 
  from customeraddresses  
) x 
where rn = 1) order by cname

Wenn Sie stattdessen alle Duplikate suchen möchten, ändern Sie einfach rn = 1 in rn> 1 . Hoffe, das hilft

0
netfed