Как выбрать N-ю строку в таблице базы данных SQL?
Мне интересно узнать некоторые (в идеале) агностические способы выбора базы данных n - я строка из таблицы базы данных. Было бы также интересно посмотреть, как этого можно достичь, используя собственные функции следующих баз данных:
- SQL Server
- в MySQL
- PostgreSQL
- SQLite
- Oracle
в настоящее время я делаю что-то вроде следующего в SQL Server 2005, но я бы будьте заинтересованы в том, чтобы увидеть другие более агностические подходы:
WITH Ordered AS (
SELECT ROW_NUMBER() OVER (ORDER BY OrderID) AS RowNumber, OrderID, OrderDate
FROM Orders)
SELECT *
FROM Ordered
WHERE RowNumber = 1000000
кредит для вышеуказанного SQL:Firoz Ансари блог
обновление: посмотреть ответ Троэльса Арвина относительно стандарта SQL. Троэльс, у вас есть какие-нибудь ссылки, которые мы можем привести?
29 ответов
есть способы сделать это в необязательных частях стандарта, но многие базы данных поддерживают свой собственный способ сделать это.
действительно хороший сайт, который говорит об этом и других вещах http://troels.arvin.dk/db/rdbms/#select-limit.
в принципе, PostgreSQL и MySQL поддерживают нестандартные:
SELECT...
LIMIT y OFFSET x
Oracle, DB2 и MSSQL поддерживают стандартные оконные функции:
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY key ASC) AS rownumber,
columns
FROM tablename
) AS foo
WHERE rownumber <= n
(который я только что скопировал из сайт связан выше, так как я никогда не использую эти DBs)
обновление: начиная с PostgreSQL 8.4 поддерживаются стандартные оконные функции, поэтому ожидайте, что второй пример будет работать и для PostgreSQL.
на LIMIT
/ OFFSET
синтаксис в PostgreSQL - это:
SELECT
*
FROM
mytable
ORDER BY
somefield
LIMIT 1 OFFSET 20;
в этом примере выбирается 21-я строка. OFFSET 20
говорит Postgres пропустить первые 20 записей. Если вы не укажете ORDER BY
пункт, нет никакой гарантии, какую запись вы получите обратно, что редко бывает полезно.
по-видимому, стандарт SQL молчит о предельной проблеме за пределами сумасшедших оконных функций, поэтому все реализуют его по-разному.
Я не уверен ни в одном из остальных, но я знаю, что SQLite и MySQL не имеют никакого порядка строк "по умолчанию". В этих двух диалектах, по крайней мере, следующий фрагмент захватывает 15-ю запись из the_table, сортируя по дате/времени, когда она была добавлена:
SELECT * FROM the_table ORDER BY added DESC LIMIT 1,15
(конечно, вам нужно будет добавить поле DATETIME и установить его на дату/время, когда была добавлена запись...)
SQL 2005 и выше имеет эту встроенную функцию. Используйте функцию ROW_NUMBER (). Он отлично подходит для веб-страниц с > стиль просмотра:
синтаксис:
SELECT
*
FROM
(
SELECT
ROW_NUMBER () OVER (ORDER BY MyColumnToOrderBy) AS RowNum,
*
FROM
Table_1
) sub
WHERE
RowNum = 23
Я подозреваю, что это дико неэффективно, но это довольно простой подход, который работал над небольшим набором данных, который я пробовал.
select top 1 field
from table
where field in (select top 5 field from table order by field asc)
order by field desc
Это получит 5-й элемент, измените второй верхний номер, чтобы получить другой N-й элемент
SQL server только (я думаю), но должен работать на более старых версиях, которые не поддерживают ROW_NUMBER ().
проверьте это на SQL Server:
Select top 10 * From emp
EXCEPT
Select top 9 * From emp
Это даст вам 10-ю строку таблицы emp!
вопреки тому, что утверждают некоторые ответы, стандарт SQL не молчит по этому вопросу.
начиная с SQL: 2003 вы можете использовать" оконные функции " для пропуска строк и ограничения результирующих наборов.
и в SQL: 2008 был добавлен несколько более простой подход, используя
OFFSET skip ROWS
FETCH FIRST n ROWS ONLY
лично я не думаю, что добавление SQL:2008 действительно было необходимо, поэтому, если бы я был ISO, я бы сохранил его из уже довольно большого стандарта.
когда мы работали в MSSQL 2000, мы делали то, что называли "тройным флипом":
редактировать
DECLARE @InnerPageSize int
DECLARE @OuterPageSize int
DECLARE @Count int
SELECT @Count = COUNT(<column>) FROM <TABLE>
SET @InnerPageSize = @PageNum * @PageSize
SET @OuterPageSize = @Count - ((@PageNum - 1) * @PageSize)
IF (@OuterPageSize < 0)
SET @OuterPageSize = 0
ELSE IF (@OuterPageSize > @PageSize)
SET @OuterPageSize = @PageSize
DECLARE @sql NVARCHAR(8000)
SET @sql = 'SELECT * FROM
(
SELECT TOP ' + CAST(@OuterPageSize AS nvarchar(5)) + ' * FROM
(
SELECT TOP ' + CAST(@InnerPageSize AS nvarchar(5)) + ' * FROM <TABLE> ORDER BY <column> ASC
) AS t1 ORDER BY <column> DESC
) AS t2 ORDER BY <column> ASC'
PRINT @sql
EXECUTE sp_executesql @sql
SQL SERVER
выберите N-ю запись сверху
SELECT * FROM (
SELECT
ID, NAME, ROW_NUMBER() OVER(ORDER BY ID) AS ROW
FROM TABLE
) AS TMP
WHERE ROW = n
выберите N-ю запись снизу
SELECT * FROM (
SELECT
ID, NAME, ROW_NUMBER() OVER(ORDER BY ID DESC) AS ROW
FROM TABLE
) AS TMP
WHERE ROW = n
вот быстрое решение вашей путаницы.
SELECT * FROM table ORDER BY `id` DESC LIMIT N, 1
здесь вы можете получить последнюю строку, заполнив N=0, вторую последнюю N=1, четвертую последнюю, заполнив N=3 и так далее.
Это очень распространенный вопрос на собеседовании и это очень простой ответ на это.
далее, Если вы хотите сумму, ID или некоторый числовой порядок сортировки, чем u может пойти для функции CAST в MySQL.
SELECT DISTINCT (`amount`) FROM cart ORDER BY CAST( `amount` AS SIGNED ) DESC LIMIT 4 , 1
здесь, заполнив N = 4, Вы сможете получить пятую последнюю запись Наибольшее количество из таблицы корзины. Вы можете соответствовать вашему полю и имени таблицы и придумать решение.
ограничение n, 1 не работает в MS SQL Server. Я думаю, что это единственная крупная база данных, которая не поддерживает этот синтаксис. Справедливости ради, он не является частью стандарта SQL, хотя он настолько широко поддерживается, что должен быть. Во всем, кроме SQL server LIMIT отлично работает. Для SQL server я не смог найти элегантное решение.
вот общая версия sproc, которую я недавно написал для Oracle, которая позволяет динамическую подкачку / сортировку-HTH
-- p_LowerBound = first row # in the returned set; if second page of 10 rows,
-- this would be 11 (-1 for unbounded/not set)
-- p_UpperBound = last row # in the returned set; if second page of 10 rows,
-- this would be 20 (-1 for unbounded/not set)
OPEN o_Cursor FOR
SELECT * FROM (
SELECT
Column1,
Column2
rownum AS rn
FROM
(
SELECT
tbl.Column1,
tbl.column2
FROM MyTable tbl
WHERE
tbl.Column1 = p_PKParam OR
tbl.Column1 = -1
ORDER BY
DECODE(p_sortOrder, 'A', DECODE(p_sortColumn, 1, Column1, 'X'),'X'),
DECODE(p_sortOrder, 'D', DECODE(p_sortColumn, 1, Column1, 'X'),'X') DESC,
DECODE(p_sortOrder, 'A', DECODE(p_sortColumn, 2, Column2, sysdate),sysdate),
DECODE(p_sortOrder, 'D', DECODE(p_sortColumn, 2, Column2, sysdate),sysdate) DESC
))
WHERE
(rn >= p_lowerBound OR p_lowerBound = -1) AND
(rn <= p_upperBound OR p_upperBound = -1);
но на самом деле, разве все это не просто салонные трюки для хорошего дизайна базы данных в первую очередь? Несколько раз мне нужна была такая функциональность, как это, для простого запроса, чтобы сделать быстрый отчет. Для любой реальной работы использование таких трюков вызывает проблемы. Если требуется выбрать определенную строку, просто имейте столбец с последовательным значением и сделайте это.
например, если вы хотите выбрать каждую 10-ю строку в MSSQL, вы можете использовать;
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY ColumnName1 ASC) AS rownumber, ColumnName1, ColumnName2
FROM TableName
) AS foo
WHERE rownumber % 10 = 0
просто возьмите мод и изменить номер 10 здесь любое число, которое вы хотите.
в Sybase SQL в любом месте:
SELECT TOP 1 START AT n * from table ORDER BY whatever
Не забывайте порядок ПО или это бессмысленно.
для SQL Server общий способ перейти по номеру строки таков: Установите ROWCOUNT @row --@row = номер строки, над которой вы хотите работать.
Например:
set rowcount 20 --устанавливает строку в 20-ю строку
выберите мясо, сыр из dbo.сэндвич --выберите столбцы из таблицы в 20-й строке
set rowcount 0 --устанавливает rowcount обратно во все строки
Это вернет информацию 20-го ряда. Обязательно поставьте в rowcount 0 потом.
Я знаю noobish, но я SQL noob, и я использовал его, так что что я могу сказать?
T-SQL-выбор N-го номера записи из таблицы
select * from
(select row_number() over (order by Rand() desc) as Rno,* from TableName) T where T.Rno = RecordNumber
Where RecordNumber --> Record Number to Select
TableName --> To be Replaced with your Table Name
например, чтобы выбрать 5-ю запись из таблицы сотрудника, ваш запрос должен быть
select * from
(select row_number() over (order by Rand() desc) as Rno,* from Employee) T where T.Rno = 5
SELECT
top 1 *
FROM
table_name
WHERE
column_name IN (
SELECT
top N column_name
FROM
TABLE
ORDER BY
column_name
)
ORDER BY
column_name DESC
Я написал этот запрос для поиска N-й строки. Пример с этим запросом будет
SELECT
top 1 *
FROM
Employee
WHERE
emp_id IN (
SELECT
top 7 emp_id
FROM
Employee
ORDER BY
emp_id
)
ORDER BY
emp_id DESC
невероятно, что вы можете найти SQL engine, выполняющий этот ...
WITH sentence AS
(SELECT
stuff,
row = ROW_NUMBER() OVER (ORDER BY Id)
FROM
SentenceType
)
SELECT
sen.stuff
FROM sentence sen
WHERE sen.row = (ABS(CHECKSUM(NEWID())) % 100) + 1
ничего необычного,никаких специальных функций, если вы используете Caché, как я...
SELECT TOP 1 * FROM (
SELECT TOP n * FROM <table>
ORDER BY ID Desc
)
ORDER BY ID ASC
учитывая, что у вас есть столбец ID или столбец datestamp, которому вы можете доверять.
вот как я бы сделал это в DB2 SQL, я считаю, что rrn (относительный номер записи) хранится в таблице O/S;
SELECT * FROM (
SELECT RRN(FOO) AS RRN, FOO.*
FROM FOO
ORDER BY RRN(FOO)) BAR
WHERE BAR.RRN = recordnumber
select * from
(select * from ordered order by order_id limit 100) x order by
x.order_id desc limit 1;
Сначала выберите верхние 100 строк по возрастанию, а затем выберите последнюю строку по убыванию и ограничьте до 1. Однако это очень дорогое утверждение, поскольку оно дважды обращается к данным.
Мне кажется, что для эффективности вам нужно 1) создать случайное число от 0 до одного меньше, чем количество записей базы данных, и 2) иметь возможность выбрать строку в этой позиции. К сожалению, разные базы данных имеют разные генераторы случайных чисел и разные способы выбора строки в позиции в результирующем наборе - обычно вы указываете, сколько строк пропустить и сколько строк вы хотите, но это делается по-разному для разных баз данных. Вот то, что работает для меня в SQLite:
select *
from Table
limit abs(random()) % (select count(*) from Words), 1;
Это зависит от возможности использовать подзапрос в предложении limit (которое в SQLite является LIMIT
в Oracle 12c вы можете использовать С ORDER BY
например, чтобы получить 3-ю запись сверху:
SELECT *
FROM sometable
ORDER BY column_name
OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY;
для SQL server следующая строка возвращает первую строку из данной таблицы.
declare @rowNumber int = 1;
select TOP(@rowNumber) * from [dbo].[someTable];
EXCEPT
select TOP(@rowNumber - 1) * from [dbo].[someTable];
вы можете перебирать значения примерно так:
WHILE @constVar > 0
BEGIN
declare @rowNumber int = @consVar;
select TOP(@rowNumber) * from [dbo].[someTable];
EXCEPT
select TOP(@rowNumber - 1) * from [dbo].[someTable];
SET @constVar = @constVar - 1;
END;