Bir sütunun her benzersiz değeri için yalnızca ilk satır nasıl seçilir


97

Diyelim ki bir müşteri adresleri tablom var:

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

Tabloda, John Smith gibi bir müşterinin birden çok adresi olabilir. Bu tablonun yalnızca 'CName'de yinelenenlerin bulunduğu ilk satırı döndürmesi için seçme sorgusuna ihtiyacım var. Bu tablo için 3. (veya 1'inci - bu iki adresten herhangi biri uygundur, ancak yalnızca biri döndürülebilir) dışındaki tüm satırları döndürmelidir. Sunucunun sütun değerini daha önce görüp görmediğine bağlı olarak filtrelemek için SELECT sorgusuna ekleyebileceğim bir anahtar kelime var mı?

Yanıtlar:


127

Hangi adresin kullanıldığını umursamadığınızı söylerseniz çok basit bir cevap.

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

İlkini, örneğin "eklenen" bir sütuna göre istiyorsanız, o zaman bu farklı bir sorgu

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

10 sütun seçerken bu şekilde kullanılması amaçlanmayabilir. Ayrıca, bit türünden bir sütunu kabul edemiyor gibi görünüyor.
nuit9

1
@ nuit9: Tabii ki bit ve 10 sütunla çalışmayacak. Bu gerçeklerden hiçbiri sizin sorunuzda yok. 2. tekniği veya Ben Thul'un tekniğini kullanırsınız. Daha genel olarak nasıl çözüleceğine dair ipuçları vererek, özellikle sorduğunuz şeyi yanıtladım.
gbn

İlk bölüm, bit tipi sütunlarla olmasa da birden çok sütunla çalışır. Bunu MS SQL server 2016'da test ettim.
2018

27

SQL 2k5 + 'da aşağıdaki gibi bir şey yapabilirsiniz:

;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

6
Lütfen sıralama, bölümleme ve [r] 'nin ne yaptığını açıklayın
Roberto

10

row_number()Satırın satır numarasını almak için kullanabilirsiniz . overKomutu kullanır - partition byyan tümce numaralandırmanın ne zaman yeniden başlatılacağını belirtir order byve satır numarasının neye göre sıralanacağını seçer. order bySorgunuzun sonuna bir ekleseniz bile over, numaralandırma sırasında komuttaki sıralamayı koruyacaktır .

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

6
Postgresql'de WHERE cümlesinde pencere işlevlerine izin verilmez
ekanna

3
Buna MS-SQL için de izin verilmez.
Mixxiphoid

1
ROW_NUMBER()WhereTeradata'daki maddede de çalışmıyor
Pirate X

6

row_numer() over(partition by ...)Sözdizimini şu şekilde kullanabilirsiniz :

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

Bunun yaptığı şey row, aynı şeyi her gördüğünde artan bir sayaç olan CNameve bu olayları indeksleyen bir sütun yaratmasıdır AddressLine. Empoze where row = 1ederek CName, AddressLinealfabetik olarak önce kimin geleceğini seçebiliriz . Eğer order byidi desc, o zaman alacağını CNamekimin AddressLineson alfabetik gelir.


1

Bu size her yinelenen satırın bir satırını verecektir. Ayrıca size bit tipi sütunlar verecektir ve en azından MS Sql Sunucusunda çalışır.

(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

Bunun yerine tüm kopyaları bulmak istiyorsanız, rn = 1'i rn> 1 olarak değiştirin. Umarım bu yardımcı olur

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.