SQL - SELECT MAX () и соответствующее поле - PullRequest
6 голосов
/ 19 июня 2009

То, что у меня есть, это в основном проблема, которую легко решить с помощью нескольких таблиц, но у меня есть только одна таблица для этого.

Рассмотрим следующую таблицу базы данных

UserID UserName EmailAddress         Source
3K3S9  Ben      ben@myisp.com        user
SF13F  Harry    lharry_x@hotbail.com 3rd_party
SF13F  Harry    reside@domain.com    user
76DSA  Lisa     cake@insider.com     user
OL39F  Nick     stick@whatever.com   3rd_party
8F66S  Stan     myman@lol.com        user

Мне нужно выбрать все поля, но только кто каждый пользователь один раз вместе с одним из их адресов электронной почты («самый большой», как определено функцией MAX ()). Это результат, который я после ...

UserID UserName EmailAddress         Source
3K3S9  Ben      ben@myisp.com        user
SF13F  Harry    lharry_x@hotbail.com 3rd_party
76DSA  Lisa     cake@insider.com     user
OL39F  Nick     stick@whatever.com   3rd_party
8F66S  Stan     myman@lol.com        user

Как видите, «Гарри» отображается только один раз, а его «самый высокий» адрес электронной почты соответствует «источнику»

В настоящее время происходит группировка по UserID, UserName и использование MAX () для EmailAddress и Source, но максимум этих двух полей не всегда совпадает, они должны быть из одной записи.

Я попробовал другой процесс, объединив таблицу с самим собой, но мне удалось получить только правильный адрес электронной почты, но не соответствующий «источник» для этого адреса.

Буду признателен за любую помощь, так как я слишком долго пытался решить эту проблему:)

Ответы [ 4 ]

8 голосов
/ 19 июня 2009

Если вы используете SQL Server 2005 или выше,

SELECT  UserID, UserName, EmailAddress, Source
FROM    (SELECT UserID, UserName, EmailAddress, Source,
                ROW_NUMBER() OVER (PARTITION BY UserID
                                   ORDER BY EmailAddress DESC) 
                    AS RowNumber
         FROM   MyTable) AS a
WHERE   a.RowNumber = 1

Конечно, есть способы выполнить ту же задачу без функций ранжирования (SQL-Standard), таких как ROW_NUMBER, которые SQL Server реализовывал только с 2005 года, включая вложенные зависимые запросы и самостоятельные объединения с ON включая трюки '>' и WHERE ... IS NULL - но функции ранжирования делают код читаемым и (теоретически) хорошо оптимизируемым механизмом SQL Server.

Редактировать: эта статья - хороший учебник по ранжированию, но в примерах используется RANK вместо ROW_NUMBER (или другой функции ранжирования, DENSE_RANK) - различие имеет значение когда есть «связи» между сгруппированными строками в одном и том же разделе в соответствии с критериями упорядочения. этот пост хорошо объясняет разницу.

5 голосов
/ 19 июня 2009
select distinct * from table t1
where EmailAddress = 
(select max(EmailAddress) from table t2
where t1.userId = t2.userId)
0 голосов
/ 27 февраля 2010

Мне кажется, у меня есть решение, которое отличается от уже предложенного:

select *
from foo
where id = (
  select id
  from foo F
  where F.bar = foo.bar
  order by F.baz
  limit 1
)

Это дает вам все записи foo, которые имеют наибольший базис по сравнению с другими записями foo с той же полосой.

0 голосов
/ 19 июня 2009
select distinct
     *  
from    
   SomeTable a
inner join (
  select max(emailAddress), userId
  from
     SomeTable 
  group by 
     userId
) b on a.emailAddress = b.emailAddress and a.userId = b.userId
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...