Как выбрать только первые строки для каждого уникального значения столбца
Допустим у меня есть таблица адресов клиентов:
CName | AddressLine
-------------------------------
John Smith | 123 Nowheresville
Jane Doe | 456 Evergreen Terrace
John Smith | 999 Somewhereelse
Joe Bloggs | 1 Second Ave
в таблице, один клиент как Джон Смит может иметь несколько адресов. Мне нужно, чтобы запрос select для этой таблицы возвращал только первую строку, найденную там, где есть дубликаты в "CName". Для этой таблицы он должен возвращать все строки, кроме 3-го (или 1 - го-любой из этих двух адресов в порядке, но только один может быть возвращен). Есть ли ключевое слово, которое я могу добавить в запрос SELECT для фильтрации на основе того, имеет ли сервер уже видели значение столбца раньше?
5 ответов:
очень простой ответ, если вы говорите, что вам все равно, какой адрес используется.
SELECT CName, MIN(AddressLine) FROM MyTable GROUP BY CName
Если вы хотите первый в соответствии, скажем, с" вставленным " столбцом, то это другой запрос
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
в SQL 2k5+, вы можете сделать что-то вроде:
;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
можно использовать
row_number()
получить номер строки. Он использует - тегpartition by
предложение указывает, когда следует перезапустить нумерацию иorder by
выбор того, что заказать номер строки. Даже если вы добавилиorder by
до конца вашего запроса он сохранит порядок в при нумерации.select * from mytable where row_number() over(partition by Name order by AddressLine) = 1
можно использовать
row_numer() over(partition by ...)
синтаксис такой:select * from ( select * , ROW_NUMBER() OVER(PARTITION BY CName ORDER BY AddressLine) AS row from myTable ) as a where row = 1
что это делает, так это то, что он создает столбец под названием
row
, который является счетчиком, который увеличивается каждый раз, когда он видит то же самоеCName
, и индексирует эти вхождения поAddressLine
. Путем наложенияwhere row = 1
, можно выбратьCName
чейAddressLine
приходит первым в алфавитном порядке. Еслиorder by
былdesc
, то он бы выбралCName
чейAddressLine
идет последним в алфавитном порядке.
Это даст вам одну строку из каждой повторяющейся строки. Он также даст вам столбцы битового типа, и он работает, по крайней мере, в 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
Если вы хотите найти все дубликаты вместо этого, просто измените rn= 1 на rn > 1. Надеюсь, это поможет