Может ли быть независимый от базы данных SQL-запрос для выборки первых N строк? - PullRequest
0 голосов
/ 05 мая 2009

Мы хотим иметь возможность выбирать первые N строк, используя SQL-запрос. Целевая база данных может быть Oracle или MySQL. Есть ли элегантный подход к этому? (Излишне говорить, что мы имеем дело с отсортированными данными здесь.)

Ответы [ 6 ]

2 голосов
/ 06 мая 2009

Чтобы получить 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 

Я считаю, что это должно работать в большинстве мест.

2 голосов
/ 05 мая 2009

Нет. Синтаксис другой.

Однако вы можете создавать виды:

/* 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
1 голос
/ 05 мая 2009

Если на столе есть уникальный ключ, то да ...

Select * From Table O
Where (Select Count(*) From Table I
       Where [UniqueKeyValue] < O.UniqueKeyValue)  < N

Вы можете заменить свои собственные критерии, если хотите, чтобы определение "Top" основывалось на какой-то другой логике, а не на уникальном ключе ...

РЕДАКТИРОВАТЬ: если «сортировка», определяющая значение «Top», основана на неуникальном столбце или наборе столбцов, то вы все равно можете использовать это, но не можете гарантировать, что сможете получить ровно N записей ...

  Select * From Table O
  Where (Select Count(*) From Table I
         Where nonUniqueCol < O.nonUniqueCol) < 10

Если записи 8, 9, 10, 11 и 12 имеют одинаковое значение в [nonUniqueCol], то запрос будет генерировать только 7 записей (с '<') ... или 12 (если вы используйте '<=') </p>

ПРИМЕЧАНИЕ. Поскольку это связано с коррелированным подзапросом, производительность может быть проблемой для очень больших таблиц ...

1 голос
/ 05 мая 2009

Я не думаю, что это возможно даже между mysql и mssql. Я делаю вариант для моделирования такого поведения, хотя:

  1. создание представлений с автоматически увеличивающимся столбцом int; скажем 'PagingHelperID'
  2. написать запрос, например: SELECT columns FROM viewname WHERE PagingHelperID BETWEEN startindex AND stopindex

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

Вы также можете "переписать" свой sql на лету при запросах в зависимости от базы данных и определить свой собственный метод для переписчика, но я не думаю, что существует какой-либо "хороший" способ сделать это.

0 голосов
/ 05 мая 2009

Большая проблема, после просмотра этого, состоит в том, что 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)

0 голосов
/ 05 мая 2009

Я думаю, что каждый продукт использует свой синтаксис для достижения этой цели. Пожалуйста, найдите похожий вопрос ниже. Существует ли альтернатива ANSI SQL ключевому слову MYSQL LIMIT?

...