Я хотел бы найти различные способы решения реальной жизненной проблемы: представьте, что у меня есть конкурс или игра, во время которой пользователи набирают очки. Вы должны создать запрос, чтобы показать список пользователей с лучшими оценками "n".
Я привожу пример, чтобы прояснить ситуацию. Допустим, это таблица Users с заработанными баллами:
UserId - Points
1 - 100
2 - 75
3 - 50
4 - 50
5 - 50
6 - 25
Если я хочу получить 3 лучших результата, результат будет следующим:
UserId - Points
1 - 100
2 - 75
3 - 50
4 - 50
5 - 50
Это может быть реализовано в виде или в хранимой процедуре по вашему желанию. Моя целевая база данных - это Sql Server. На самом деле я решил это, но я думаю, что есть другой способ получить результат ... быстрее или эффективнее, чем мой.


Не проверено, но должно работать:
select * from users where points in
(select distinct top 3 points from users order by points desc)
@bosnic, я не думаю, что это сработает, как просили, я не так хорошо знаком с MS SQL, но я ожидал, что он вернет только 3 строки и проигнорирует тот факт, что 3 пользователя привязаны к 3-му месту.
Примерно так должно работать:
select userid, points
from scores
where points in (select top 3 points
from scores
order by points desc)
order by points desc
@Espo благодарит за проверку реальности - добавлен подвыбор, чтобы исправить это.
Думаю, самый простой ответ:
select userid, points from users
where points in (select distinct top N points from users order by points desc)
Если вы хотите поместить это в сохраненную процедуру, которая принимает N в качестве параметра, вам придется либо прочитать SQL в переменную, а затем выполнить его, либо выполнить трюк с подсчетом строк:
declare @SQL nvarchar(2000)
set @SQL = "select userID, points from users "
set @SQL = @SQL + " where points in (select distinct top " + @N
set @SQL = @SQL + " points from users order by points desc)"
execute @SQL
или же
SELECT UserID, Points
FROM (SELECT ROW_NUMBER() OVER (ORDER BY points DESC)
AS Row, UserID, Points FROM Users)
AS usersWithPoints
WHERE Row between 0 and @N
Оба примера предполагают использование SQL Server и не тестировались.
@ Роб # 37760:
select top N points from users order by points desc
Этот запрос выберет только 3 строки, если N равно 3, см. Вопрос. «Верхняя 3» должна вернуть 5 строк.
Как насчет:
select top 3 with ties points
from scores
order by points desc
Не уверен, что "со связями" работает на чем-нибудь другом SQL Server.
В SQL Server 2005 и более поздних версиях вы можете передать "верхнее" число как параметр типа int:
select top (@n) with ties points
from scores
order by points desc
Вот тот, который работает - я не знаю, эффективнее ли он, и это SQL Server 2005+.
with scores as (
select 1 userid, 100 points
union select 2, 75
union select 3, 50
union select 4, 50
union select 5, 50
union select 6, 25
),
results as (
select userid, points, RANK() over (order by points desc) as ranking
from scores
)
select userid, points, ranking
from results
where ranking <= 3
Очевидно, что первое «с» - это установка значений, так что вы можете протестировать второе с помощью и окончательный выбор работы - вы можете начать с «с результатами как ...», если бы вы выполняли запрос к существующей таблице.
@ Мэтт Гамильтон
Ваш ответ работает с приведенным выше примером, но не будет работать, если набор данных будет 100, 75, 75, 50, 50 (где он вернет только 3 строки). TOP WITH TIES включает только связи последней возвращенной строки ...
Crucible получил это (при условии, что SQL 2005 - это вариант).
На самом деле модификация WHERE IN с использованием INNER JOIN будет намного быстрее.
SELECT
userid, points
FROM users u
INNER JOIN
(
SELECT DISTINCT TOP N
points
FROM users
ORDER BY points DESC
) AS p ON p.points = u.points
Попробуй это
select top N points from users order by points desc
Эй, я нашел все остальные ответы немного длинными и неэффективными Мой ответ был бы таким:
select * from users order by points desc limit 0,5
это отобразит верхние 5 баллов
У меня аналогичная проблема, и я пытался использовать MAX, а затем я прочитал ваш ответ и вспомнил DENSE_RANK. Сэкономил мне много времени.