Мы хотим, чтобы выбрать верхние N строк, используя SQL-запрос. Целевой базой данных может быть Oracle или MySQL. Есть ли элегантный подход к этому? (Излишне говорить, что мы имеем дело с отсортированными данными здесь.)
Чтобы получить 5 лучших счетчиков из этой таблицы:
CREATE TABLE people
(id int,
name string,
score int)
попробуйте этот SQL:
SELECT id,
name,
score
FROM people p
WHERE (SELECT COUNT(*)
FROM people p2
WHERE p2.score > p.score
) <=4
Я считаю, что это должно работать в большинстве мест.
Нет. Синтаксис отличается.
Однако вы можете создавать представления:
/* Oracle */
CREATE VIEW v_table
AS
SELECT *
FROM (
SELECT *
FROM table
ORDER BY
column
)
WHERE rownum <= n
/* MySQL */
CREATE VIEW v_table
AS
SELECT *
FROM table
ORDER BY
column
LIMIT n
Если в таблице есть уникальный ключ, да...
Select * From Table O
Where (Select Count(*) From Table I
Where [UniqueKeyValue] < O.UniqueKeyValue) < N
Вы можете заменить свои собственные критерии, если хотите, чтобы определение "Верх" было основано на какой-то другой логике, чем на уникальном ключе...
EDIT: если "сортировка", определяющая значение "Верх", основана на не уникальном столбце или наборе столбцов, то вы все равно можете использовать это, но вы не можете гарантировать, что сможете получить ровно N записей...
Select * From Table O
Where (Select Count(*) From Table I
Where nonUniqueCol < O.nonUniqueCol) < 10
Если записи 8, 9, 10, 11 и 12 имеют одинаковое значение в [nonUniqueCol], тогда запрос будет генерировать только 7 записей (с '<')... или 12 (если вы используете '< =')
ПРИМЕЧАНИЕ. Поскольку это связано с коррелированным подзапросом, производительность может быть проблемой для очень больших таблиц...
Я не думаю, что это возможно даже между mysql и mssql. Я делаю выбор для моделирования такого поведения, хотя:
SELECT columns FROM viewname WHERE PagingHelperID BETWEEN startindex AND stopindex
Это затруднит упорядочение, вам понадобятся разные представления для каждого порядка, в котором вы намерены извлекать данные.
Вы также можете "переписать" свой sql "на лету" при запросе в зависимости от базы данных и определить свой собственный метод для перезаписывающего устройства, но я не думаю, что есть "хороший" способ сделать это.
Большая проблема, рассмотрев это, заключается в том, что MySQL не соответствует требованиям ISO SQL: 2003. Если бы это было так, у вас были бы удобные функции окна:
SELECT * from
( SELECT
RANK() OVER (ORDER BY <blah>) AS ranking,
<rest of columns here>,
FROM <table>
)
WHERE ranking <= <N>
Увы, MySQL (и другие, которые имитируют его поведение, например SQLite), не являются, следовательно, всей предельной проблемой.
Отметьте этот фрагмент из Википедии (http://en.wikipedia.org/wiki/Window_function_(SQL)#Limiting_result_rows)
Я думаю, что для достижения этого каждый продукт следует за другим синтаксисом. Пожалуйста, найдите аналогичный вопрос ниже. Есть ли альтернатива ANSI SQL для ключевого слова LIMIT MYSQL?