SQL'e göre benzersiz kayıtlar nasıl seçilir


89

"SELECT * FROM table" i gerçekleştirdiğimde aşağıdaki gibi sonuçlar aldım:

1 item1 data1
2 item1 data2
3 item2 data3
4 item3 data4

Gördüğünüz gibi, 2. sütundan yinelenen kayıtlar var (öğe1 yinelenmiş). Öyleyse nasıl böyle bir sonuç alabilirim:

1 item1 data1
2 item2 data3
3 item3 data4

Yinelenen kayıtlardan, benzersiz kayıtların geri kalanıyla birlikte yalnızca bir kayıt döndürülür.


Öğe 1 teknik olarak kopyalanmamış. Gösterildiği gibi, 1. ve 2. satırlar benzersiz gözlemlerdir. Ya 1. satırı değil 2. satırı tutmak istersen?
Cybernetic

Yanıtlar:


107

İle distincttekli ve çoklu kolon adları ile anahtar kelime, sizi farklı kayıtlar olsun:

SELECT DISTINCT column 1, column 2, ...
FROM table_name;

15
Cevap gerçekten yanlış olabilir mi? DISTINCT, seçilen tüm sütunlara (en azından bir DB2'de) uygulanır ve bu sütun, yine de tek tek sütunlarda yinelenen değerler döndürür.
Konstantin

26

Yalnızca kopyaları kaldırmanız gerekiyorsa kullanın DISTINCT. GROUP BYher bir gruba toplu operatörler uygulamak için kullanılmalıdır

GROUP BY v DISTINCT


11

Her benzersiz öğe için hangi sıraya dönmek istediğinize bağlıdır. Verileriniz, bu durumda SQL Server için minimum veri değerini gösteriyor gibi görünüyor.

SELECT item, min(data)
FROM  table
GROUP BY item

11

Kullanabileceğiniz 4 yöntem vardır:

  1. DISTINCT
  2. GRUPLAMA
  3. Alt sorgu
  4. ROW_NUMBER () ile Ortak Tablo İfadesi (CTE)

TABLETest verileriyle birlikte aşağıdaki örneği düşünün :

/** Create test table */
CREATE TEMPORARY TABLE dupes(word text, num int, id int);

/** Add test data with duplicates */
INSERT INTO dupes(word, num, id)
VALUES ('aaa', 100, 1)
      ,('bbb', 200, 2)
      ,('ccc', 300, 3)
      ,('bbb', 400, 4)
      ,('bbb', 200, 5)     -- duplicate
      ,('ccc', 300, 6)     -- duplicate
      ,('ddd', 400, 7)
      ,('bbb', 400, 8)     -- duplicate
      ,('aaa', 100, 9)     -- duplicate
      ,('ccc', 300, 10);   -- duplicate

Seçenek 1: DISTINCT SEÇİN

Bu en basit ve anlaşılır, ancak aynı zamanda en sınırlı yoldur:

SELECT DISTINCT word, num 
FROM    dupes
ORDER BY word, num;

/*
word|num|
----|---|
aaa |100|
bbb |200|
bbb |400|
ccc |300|
ddd |400|
*/

2. Seçenek: GRUPLAMA

Gruplama, gibi, toplanan verileri eklemenize olanak verir min(id), max(id), count(*)vb:

SELECT  word, num, min(id), max(id), count(*)
FROM    dupes
GROUP BY word, num
ORDER BY word, num;

/*
word|num|min|max|count|
----|---|---|---|-----|
aaa |100|  1|  9|    2|
bbb |200|  2|  5|    2|
bbb |400|  4|  8|    2|
ccc |300|  3| 10|    3|
ddd |400|  7|  7|    1|
*/

3. Seçenek: Alt sorgu

Bir alt sorgu kullanarak, önce yok sayılacak yinelenen satırları belirleyebilir ve ardından bunları WHERE NOT IN (subquery)yapıyla dış sorguda filtreleyebilirsiniz :

/** Find the higher id values of duplicates, distinct only added for clarity */
    SELECT  distinct d2.id
    FROM    dupes d1
        INNER JOIN dupes d2 ON d2.word=d1.word AND d2.num=d1.num
    WHERE d2.id > d1.id

/*
id|
--|
 5|
 6|
 8|
 9|
10|
*/

/** Use the previous query in a subquery to exclude the dupliates with higher id values */
SELECT  *
FROM    dupes
WHERE   id NOT IN (
    SELECT  d2.id
    FROM    dupes d1
        INNER JOIN dupes d2 ON d2.word=d1.word AND d2.num=d1.num
    WHERE d2.id > d1.id
)
ORDER BY word, num;

/*
word|num|id|
----|---|--|
aaa |100| 1|
bbb |200| 2|
bbb |400| 4|
ccc |300| 3|
ddd |400| 7|
*/

4. Seçenek: ROW_NUMBER () ile Ortak Tablo İfadesi

Ortak Tablo İfadesinde (CTE), grup sütununa göre bölümlenmiş ve istenen sırada sıralanan ROW_NUMBER () öğesini seçin. Ardından yalnızca aşağıdakilere sahip kayıtları SEÇİN ROW_NUMBER() = 1:

WITH CTE AS (
    SELECT  *
           ,row_number() OVER(PARTITION BY word, num ORDER BY id) AS row_num
    FROM    dupes
)
SELECT  word, num, id 
FROM    cte
WHERE   row_num = 1
ORDER BY word, num;

/*
word|num|id|
----|---|--|
aaa |100| 1|
bbb |200| 2|
bbb |400| 4|
ccc |300| 3|
ddd |400| 7|
*/

6

yalnızca iç birleştirmeyi kullanın çünkü group by, bir toplama işlevinde bulunmadığını söyleyen birden çok sütunla çalışmaz.

SELECT a.*
FROM yourtable a
INNER JOIN 
  (SELECT yourcolumn,
    MIN(id) as id
  FROM yourtable 
  GROUP BY yourcolumn
) AS b
  ON a.yourcolumn= b.yourcolumn
  AND a.id = b.id;

Bu, farklı bir sorunun yanıtıdır, muhtemelen grup başına en büyük
a_horse_with_no_name

Bu ve Dave Baker'ın çözümü, SO sorusu için doğru çözümlerdir. Bu çözümün avantajı, yalnızca belirli belirli sütunlara sahip satırların seçilmesine izin vermesidir ve birden çok belirtilen sütundan yalnızca birini seçmek için bir sütun MIN (id) AS id tanımlanmalıdır.
giordano


1

Sonucunuzdaki tüm sütunları almak için aşağıdaki gibi bir şey yerleştirmeniz gerekir:

SELECT distinct a, Table.* FROM Table

o yerleştirecektir bir ilk sütun olarak ve geri kalan TÜM tanımına aynı sırada sütunların olacaktır. Bu, sütun a tekrarlanacak.


1
Bundan emin misin? Bunu w3schools üzerinde denedim ve SELECT * ile aynı sonucu verdi, ancak a ilk sütun
Freakishly

@ Çılgınca evet ve cevabımda yapacağı tam olarak bu: /
htafoya

Bu işe yaramaz, bunun gibi farklı
olandan

@Mohsinkhan peki masa adını yazmanız gereken yeri unuttum. Her nasılsa bunu yazdığımda işe yaradı ama şimdi test ettim ve tablo adı olmadan önce *
htafoya

2
Bu,select distinct * from ...
a_horse_with_no_name

-4

ABC.CODE_DIM'den (EFF_ST, ROW_NUMBER () üzerinden (eff_st TARAFINDAN BÖLME) XYZ arasından Eff_st seçin

) burada XYZ = 1 EFF_ST siparişi yalnızca ilk 5 satırı getir

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.