SQL 데이터베이스 테이블에서 n 번째 행을 선택하는 방법은 무엇입니까?
데이터베이스 테이블에서 n 번째 행 을 선택하는 (이상적으로) 데이터베이스 불가지론 적 방법을 배우고 싶습니다 . 다음 데이터베이스의 고유 기능을 사용하여 이것이 어떻게 달성 될 수 있는지 보는 것도 흥미로울 것입니다.
- SQL 서버
- MySQL
- PostgreSQL
- SQLite
- 신탁
현재 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 Ansari의 웹 로그
업데이트 : SQL 표준에 관한 Troels Arvin의 답변을 참조하십시오 . 트롤, 우리가 인용 할 수있는 링크가 있습니까?
표준의 선택적 부분 에서이 작업을 수행하는 방법이 있지만 많은 데이터베이스가 자체 작업 방식을 지원합니다.
이것과 다른 것들에 대해 이야기하는 정말 좋은 사이트는 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
(나는 그 DB를 사용하지 않기 때문에 위에서 링크 된 사이트에서 방금 복사했습니다)
업데이트 : PostgreSQL 8.4부터 표준 윈도우 기능이 지원되므로 PostgreSQL에서도 두 번째 예제가 작동 할 것으로 예상됩니다.
업데이트 : SQLite는 2018-09-15의 버전 3.25.0에서 창 기능 지원을 추가 했으므로 두 형식 모두 SQLite에서 작동합니다.
PostgreSQL 의 LIMIT
/ OFFSET
구문 은 다음과 같습니다.
SELECT
*
FROM
mytable
ORDER BY
somefield
LIMIT 1 OFFSET 20;
이 예는 21 번째 행을 선택합니다. OFFSET 20
Postgres에 처음 20 개 레코드를 건너 뛰라고 지시합니다. ORDER BY
절을 지정하지 않으면 어떤 레코드를 되 찾을 것이라는 보장이 없으므로 거의 유용하지 않습니다.
분명히 SQL 표준은 미친 창 기능 이외의 한계 문제에 대해서는 침묵하므로 모든 사람들이 다르게 구현합니다.
나머지는 확실하지 않지만 SQLite와 MySQL에는 "기본"행 순서가 없습니다. 이 두 방언에서 최소한 다음 스 니펫은 추가 된 날짜 / 시간을 기준으로 정렬하여 the_table에서 15 번째 항목을 가져옵니다.
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
이것은 다섯 번째 항목을 얻고 두 번째 최상위 숫자를 변경하여 다른 n 번째 항목을 얻습니다.
SQL 서버에서만 (제 생각에는) ROW_NUMBER ()를 지원하지 않는 이전 버전에서 작동해야합니다.
작은 변화 1 개 : n 대신 n-1.
select *
from thetable
limit n-1, 1
SQL Server에서 확인하십시오.
Select top 10 * From emp
EXCEPT
Select top 9 * From emp
이것은 당신에게 emp 테이블의 10 번째 줄을 줄 것입니다!
일부 답변이 주장하는 것과는 달리 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 서버
위에서 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 (select foo from bar order by foo) where ROWNUM = x
혼동의 빠른 해결책은 다음과 같습니다.
SELECT * FROM table ORDER BY `id` DESC LIMIT N, 1
여기에서 N = 0을 채우면 마지막 행, N = 1에 의해 두 번째 마지막, N = 3을 채우는 네 번째 마지막 행 등을 얻을 수 있습니다.
이것은 인터뷰에서 매우 일반적인 질문이며 매우 간단한 질문입니다.
또한 u보다 Amount, ID 또는 Numeric Sorting Order를 원한다면 MySQL에서 CAST 기능을 사용할 수 있습니다.
SELECT DISTINCT (`amount`) FROM cart ORDER BY CAST( `amount` AS SIGNED ) DESC LIMIT 4 , 1
여기에 N = 4를 채우면 CART 테이블에서 최고 금액의 다섯 번째 마지막 레코드를 얻을 수 있습니다. 필드와 테이블 이름을 맞추고 솔루션을 제안 할 수 있습니다.
Oracle 12c에서는 다음 OFFSET..FETCH..ROWS
옵션을 사용할 수 있습니다ORDER BY
예를 들어, 위에서 세 번째 레코드를 얻으려면
SELECT *
FROM sometable
ORDER BY column_name
OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY;
더하다:
LIMIT n,1
결과는 결과 n에서 시작하는 하나의 결과로 제한됩니다.
예를 들어, MSSQL에서 매 10 번째 행을 선택하려면 다음을 사용할 수 있습니다.
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY ColumnName1 ASC) AS rownumber, ColumnName1, ColumnName2
FROM TableName
) AS foo
WHERE rownumber % 10 = 0
MOD를 선택하고 원하는 숫자를 10으로 변경하십시오.
LIMIT n, 1은 MS SQL Server에서 작동하지 않습니다. 나는 그것이 그 구문을 지원하지 않는 유일한 주요 데이터베이스에 불과하다고 생각합니다. 공평하게 말하면 SQL 표준의 일부는 아니지만 광범위하게 지원되어야합니다. SQL 서버를 제외한 모든 것에서 LIMIT가 훌륭하게 작동합니다. SQL 서버의 경우 우아한 솔루션을 찾을 수 없었습니다.
동적 페이징 / 정렬을 허용하는 Oracle 용으로 최근에 작성한 sproc의 일반 버전은 다음과 같습니다.
-- 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);
그러나 실제로이 모든 것이 실제로 좋은 데이터베이스 디자인을위한 팔러 트릭이 아닙니까? 몇 번이나 이와 같은 기능이 필요했기 때문에 간단한 한 번의 쿼리로 빠른 보고서를 작성했습니다. 실제 작업의 경우 이와 같은 트릭을 사용하면 문제가 발생합니다. 특정 행을 선택해야하는 경우 순차적 인 값을 가진 열만 있으면됩니다.
SQL Server의 경우 행 번호로 이동하는 일반적인 방법은 다음과 같습니다.
SET ROWCOUNT @row --@row = the row number you wish to work on.
예를 들어 :
set rowcount 20 --sets row to 20th row
select meat, cheese from dbo.sandwich --select columns from table at 20th row
set rowcount 0 --sets rowcount back to all rows
이것은 20 번째 행의 정보를 반환합니다. 이후에 행 수를 0으로 설정하십시오.
Sybase SQL Anywhere에서 :
SELECT TOP 1 START AT n * from table ORDER BY whatever
ORDER BY를 잊어 버리거나 의미가 없습니다.
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 * FROM emp a
WHERE n = (SELECT COUNT( _rowid)
FROM emp b
WHERE a. _rowid >= b. _rowid);
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 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;
이 엔진을 실행하는 SQL 엔진을 찾을 수 있다는 것을 믿을 수 없습니다 ...
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 열 또는 날짜 스탬프 열이 있다고 가정하면 신뢰할 수 있습니다.
이것이 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에서 1 사이의 난수를 생성하고 2) 해당 위치에서 행을 선택할 수 있어야합니다. 불행히도 데이터베이스마다 다른 난수 생성기와 결과 집합의 위치에서 행을 선택하는 다른 방법이 있습니다. 일반적으로 건너 뛸 행 수와 원하는 행 수를 지정하지만 데이터베이스마다 다르게 수행됩니다. 다음은 SQLite에서 나를 위해 작동하는 것입니다.
select *
from Table
limit abs(random()) % (select count(*) from Words), 1;
It does depend on being able to use a subquery in the limit clause (which in SQLite is LIMIT <recs to skip>,<recs to take>) Selecting the number of records in a table should be particularly efficient, being part of the database's meta data, but that depends on the database's implementation. Also, I don't know if the query will actually build the result set before retrieving the Nth record, but I would hope that it doesn't need to. Note that I'm not specifying an "order by" clause. It might be better to "order by" something like the primary key, which will have an index - getting the Nth record from an index might be faster if the database can't get the Nth record from the database itself without building the result set.
참고 URL : https://stackoverflow.com/questions/16568/how-to-select-the-nth-row-in-a-sql-database-table
'Programming' 카테고리의 다른 글
세계에서 봄 콩은 무엇입니까? (0) | 2020.02.27 |
---|---|
생성자에서 재정의 가능한 메서드 호출의 문제점은 무엇입니까? (0) | 2020.02.27 |
OpenCV-Python의 간단한 숫자 인식 OCR (0) | 2020.02.27 |
SQL Server 프로파일 러-한 데이터베이스의 이벤트 만 표시하도록 추적을 필터링하는 방법은 무엇입니까? (0) | 2020.02.27 |
elasticsearch가 특정 필드 만 반환하도록 하시겠습니까? (0) | 2020.02.27 |