Извлечь одну строку для идентификатора аккаунта из списка, часть 2 - PullRequest
3 голосов
/ 25 сентября 2008

Не уверен, как задать продолжение SO, но это относится к предыдущему вопросу: Извлечение одной строки для идентификатора учетной записи из списка

Запрос, с которым я работаю:

SELECT *
FROM scores s1
WHERE accountid NOT IN (SELECT accountid FROM scores s2 WHERE s1.score < s2.score)
ORDER BY score DESC

Это выбирает лучшие результаты и ограничивает результаты одной строкой на учетную запись; их лучший результат.

Последнее препятствие состоит в том, что этот запрос возвращает несколько строк для учетных записей, которые имеют множественные вхождения с их наибольшим счетом. Таким образом, если учетная запись 17 имеет оценки 40, 75, 30, 75, запрос возвращает обе строки с оценками 75.

Может ли кто-нибудь изменить этот запрос (или предоставить лучший) для исправления этого случая и действительно ограничить его одной строкой для идентификатора учетной записи?

Еще раз спасибо!

Ответы [ 6 ]

2 голосов
/ 25 сентября 2008

Если вас интересуют только учет и оценка, вы можете использовать простой запрос GROUP BY, заданный Полом выше.

SELECT accountid, MAX(score) 
FROM scores 
GROUP BY accountid;

Если вам нужны другие атрибуты из таблицы результатов, вы можете получить другие атрибуты из строки с помощью запроса, подобного следующему:

SELECT s1.*
FROM scores AS s1
  LEFT OUTER JOIN scores AS s2 ON (s1.accountid = s2.accountid 
    AND s1.score < s2.score)
WHERE s2.accountid IS NULL;

Но это все равно дает несколько строк, в вашем примере, где у данного accountid есть две оценки, соответствующие его максимальному значению. Чтобы еще больше сократить набор результатов до одной строки, например строки с последней датой игры, попробуйте следующее:

SELECT s1.*
FROM scores AS s1
  LEFT OUTER JOIN scores AS s2 ON (s1.accountid = s2.accountid 
    AND s1.score < s2.score)
  LEFT OUTER JOIN scores AS s3 ON (s1.accountid = s3.accountid 
    AND s1.score = s3.score AND s1.gamedate < s3.gamedate) 
WHERE s2.accountid IS NULL
    AND s3.accountid IS NULL;
2 голосов
/ 25 сентября 2008
select accountid, max(score) from scores group by accountid;
1 голос
/ 25 сентября 2008

Если ваша СУБД поддерживает их, тогда аналитическая функция будет хорошим подходом, особенно если вам нужны все столбцы строки.

select ...
from   (
   select accountid,
          score,
          ...
          row_number() over 
               (partition by accountid
                    order by score desc) score_rank
   from   scores)
where score_rank = 1;

Возвращаемая строка является неопределенной в описываемом вами случае, но вы можете легко изменить аналитическую функцию, например, упорядочив (Score desc, test_date desc), чтобы получить более позднюю из двух соответствующих высоких оценок.

Другие аналитические функции, основанные на ранге, достигнут аналогичной цели.

Если вы не возражаете против дубликатов, то следующее, вероятно, будет более эффективным, чем ваш текущий метод:

select ...
from   (
   select accountid,
          score,
          ...
          max(score) over (partition by accountid) max_score
   from   scores)
where score = max_score;
0 голосов
/ 25 сентября 2008

Это решение работает в MS SQL, давая вам всю строку.

SELECT *
FROM scores
WHERE scoreid in
(
  SELECT max(scoreid)
  FROM scores as s2
    JOIN
  (
    SELECT max(score) as maxscore, accountid
    FROM scores s1
    GROUP BY accountid
  ) sub ON s2.score =  sub.maxscore AND s2.accountid = s1.accountid
  GROUP BY s2.score, s2.accountid
)
0 голосов
/ 25 сентября 2008

Отличается ли ваша база данных? Как в выделенном отличном x от y?

0 голосов
/ 25 сентября 2008

Если вы выбираете подмножество столбцов, вы можете использовать ключевое слово DISTINCT для фильтрации результатов.

SELECT DISTINCT UserID, score
FROM scores s1
WHERE accountid NOT IN (SELECT accountid FROM scores s2 WHERE s1.score < s2.score)
ORDER BY score DESC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...