Kiedy wykonuję polecenie „SELECT * FROM table”, otrzymałem wyniki takie jak poniżej:
1 item1 data1
2 item1 data2
3 item2 data3
4 item3 data4
Jak widać, istnieją rekordy dup z kolumny 2 (pozycja 1 jest kopiowana). Jak więc mógłbym uzyskać taki wynik:
1 item1 data1
2 item2 data3
3 item3 data4
Tylko jeden rekord jest zwracany z duplikatu wraz z pozostałymi unikalnymi rekordami.
Odpowiedzi:
Dzięki
distinct
słowu kluczowemu z jedną i wieloma nazwami kolumn otrzymujesz różne rekordy:SELECT DISTINCT column 1, column 2, ... FROM table_name;
źródło
Jeśli chcesz tylko usunąć duplikaty, użyj
DISTINCT
.GROUP BY
należy używać do stosowania operatorów agregujących do każdej grupyGROUP BY v DISTINCT
źródło
To zależy od tego, który wiersz chcesz zwrócić za każdy unikalny przedmiot. Twoje dane wydają się wskazywać minimalną wartość danych, więc w tym przypadku dla SQL Server.
SELECT item, min(data) FROM table GROUP BY item
źródło
Istnieją 4 metody, których możesz użyć:
Rozważ następujący przykład
TABLE
z danymi testowymi:/** 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
Opcja 1: SELECT DISTINCT
Jest to najprostszy i najprostszy, ale także najbardziej ograniczony sposób:
SELECT DISTINCT word, num FROM dupes ORDER BY word, num; /* word|num| ----|---| aaa |100| bbb |200| bbb |400| ccc |300| ddd |400| */
Opcja 2: GROUP BY
Grupowanie pozwala na dodawanie zagregowane dane, podobnie jak
min(id)
,max(id)
,count(*)
itp: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| */
Opcja 3: podzapytanie
Korzystając z podzapytania, możesz najpierw zidentyfikować zduplikowane wiersze do zignorowania, a następnie odfiltrować je w zewnętrznym zapytaniu za pomocą
WHERE NOT IN (subquery)
konstrukcji:/** 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| */
Opcja 4: wspólne wyrażenie tabeli z ROW_NUMBER ()
W Common Table Expression (CTE) wybierz ROW_NUMBER (), podzielony na partycje według kolumny grupy i uporządkowany w żądanej kolejności. Następnie WYBIERZ tylko te rekordy, które mają
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| */
źródło
po prostu użyj sprzężenia wewnętrznego, ponieważ grupowanie według nie będzie działać z wieloma kolumnami, które nie są zawarte w żadnej funkcji agregującej.
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;
źródło
Uważam, że jeśli z jakiegokolwiek powodu nie mogę używać DISTINCT, to GROUP BY będzie działać.
źródło
Aby uzyskać wszystkie kolumny w swoim wyniku, musisz umieścić coś jako:
SELECT distinct a, Table.* FROM Table
zostanie on umieszczony jako pierwszej kolumny, a reszta będzie wszystkie kolumny w tej samej kolejności co definicji. Oznacza to, że kolumna a zostanie powtórzona.
źródło
select distinct * from ...
Select Eff_st from (select EFF_ST, ROW_NUMBER () over (PARTITION BY eff_st) XYZ - from ABC.CODE_DIM
) gdzie XYZ = 1 zamówienie przez EFF_ST pobierz tylko pierwsze 5 wierszy
źródło