2009-06-18 2 views
6

У меня есть проблема, которая легко решается с помощью нескольких таблиц, но для этого у меня есть только одна таблица.SQL - SELECT MAX() и сопроводительное поле

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

UserID UserName EmailAddress   Source 
3K3S9 Ben  [email protected]  user 
SF13F Harry [email protected] 3rd_party 
SF13F Harry [email protected] user 
76DSA Lisa  [email protected]  user 
OL39F Nick  [email protected] 3rd_party 
8F66S Stan  [email protected]  user 

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

UserID UserName EmailAddress   Source 
3K3S9 Ben  [email protected]  user 
SF13F Harry [email protected] 3rd_party 
76DSA Lisa  [email protected]  user 
OL39F Nick  [email protected] 3rd_party 
8F66S Stan  [email protected]  user 

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

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

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

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

+0

У вас есть дополнительная колонка с определенным первичным ключом? Является ли пара (UserId, EmailAddress) уникальной? –

ответ

7

Если вы на 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 года, включая вложенные зависимые запросы и собственные левые соединения с , включая «>» и WHERE ... IS NULL трюк - но функции ранжирования делают код, который читабельным и (теоретически) хорошо оптимизируется с помощью SQL Server Engine.

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

+0

Очень интересный Алекс, я изучу об этих возможностях. – tekBlues

+0

Это, безусловно, работает очень хорошо ... но я не понимаю синтаксис>. <Мне нужно немного прочитать, чтобы понять это :) – Nippysaurus

+0

Отредактировал мой ответ, чтобы добавить URL-адреса в два хороших, коротких учебника по ранжированию функций - HTH! –

5
select distinct * from table t1 
where EmailAddress = 
(select max(EmailAddress) from table t2 
where t1.userId = t2.userId) 
+0

Стоит отметить, что это часто может выполняться быстрее, чем принятый ответ, особенно если есть указатель на {userid, EmailAddress DESC} на t2 –

0
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 
+0

Я был бы счастливее, если условие ON включает a.userID = b.userID, а также адрес электронной почты. –

+0

Правда, это делает его более конкретным и позволяет избежать потенциальных проблем. Я отредактировал свой ответ, чтобы отразить это. –

0

Я думаю, что у меня есть решение, которое отличается от тех, которые уже предложенных:

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

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

Смежные вопросы