programing

SQL 데이터베이스 테이블의 n번째 행을 선택하려면 어떻게 해야 합니다.

minecode 2022. 10. 1. 14:03
반응형

SQL 데이터베이스 테이블의 n번째 행을 선택하려면 어떻게 해야 합니다.

데이터베이스 테이블에서 n번째 행을 선택하는 (이상적으로) 데이터베이스에 구애받지 않는 방법을 배우고 싶습니다.또한 다음 데이터베이스의 기본 기능을 사용하여 이 작업을 수행하는 방법도 볼 수 있습니다.

  • SQL Server
  • MySQL
  • 포스트그레스Ql
  • 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의 Weblog

업데이트: SQL 표준에 대한 Troels Arvin의 답변을 참조하십시오.트롤스, 우리가 인용할 수 있는 연결고리 없어?

표준에는 옵션 부분에서 이를 수행하는 방법이 있지만, 많은 데이터베이스가 자체 방식을 지원합니다.

이러한 내용을 소개하는 매우 좋은 사이트는 http://troels.arvin.dk/db/rdbms/#select-limit입니다.

기본적으로 PostgreSQL 및 MySQL은 비표준을 지원합니다.

SELECT...
LIMIT y OFFSET x 

Oracle, DB2 및 MSQL은 표준 윈도우 기능을 지원합니다.

SELECT * FROM (
  SELECT
    ROW_NUMBER() OVER (ORDER BY key ASC) AS rownumber,
    columns
  FROM tablename
) AS foo
WHERE rownumber <= n

(이러한 DB를 사용하지 않기 때문에 위에 링크된 사이트에서 복사한 것입니다.)

업데이트: PostgreSQL 8.4 표준 윈도우 기능이 지원되므로 Postgre에서 두 번째 예가 작동하기를 기대하십시오.SQL도 마찬가지입니다.

업데이트: SQLite 추가 창 기능은 2018-09-15 버전 3.25.0에서 지원되므로 두 양식 모두 SQLite에서도 작동합니다.

PostgreSQL은 SQL 표준에서 정의한 윈도 기능을 지원하지만 이 기능은 어색하기 때문에 대부분의 사용자는 (비표준) /:

SELECT
    *
FROM
    mytable
ORDER BY
    somefield
LIMIT 1 OFFSET 20;

21번입니다. OFFSET 20Postgres 20 경우ORDER BY조항, 어떤 레코드를 돌려받을지 장담할 수 없습니다. 거의 쓸모가 없습니다.

나머지는 잘 모르겠지만 SQLite와 MySQL에는 "기본" 행 순서가 없습니다.이러한 두 가지 방언에서는 적어도 다음 스니펫이 추가된 날짜/시간별로 정렬하여 테이블에서 15번째 엔트리를 가져옵니다.

SELECT * 
FROM the_table 
ORDER BY added DESC 
LIMIT 1,15

(물론 추가된 DATETIME 필드가 있어야 하며, 항목이 추가된 날짜/시간으로 설정해야 합니다.)

SQL 2005 이상에는 이 기능이 내장되어 있습니다.ROW_NUMBER() 함수를 사용합니다.<< Prev and Next >>스타일의 브라우징이 있는 Web 페이지에 최적입니다.

구문:

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라면 이미 상당히 큰 표준에서 제외했을 것입니다.

1 작은 변화: n이 아닌 n-1.

select *
from thetable
limit n-1, 1

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

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

우아하지도, 빠르지도 않았지만 효과가 있었어요

12c를 사용할 수 .OFFSET..FETCH..ROWS을 지정합니다.ORDER BY

예를 들어, 위에서 세 번째 레코드를 가져오려면:

SELECT * 
FROM   sometable
ORDER BY column_name
OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY;

여기 당신의 혼란에 대한 빠른 해결책이 있습니다.

SELECT * FROM table ORDER BY `id` DESC LIMIT N, 1

여기서 마지막 행은 N=0 채우기, 두 번째 마지막 행은 N=1, 네 번째 마지막 행은 N=3 채우기 등으로 얻을 수 있습니다.

이것은 면접에서 매우 흔한 질문이며, 이것은 매우 간단하다.

또한 금액, ID 또는 숫자 정렬 순서를 원할 경우 MySQL에서 CAST 기능을 사용할 수 있습니다.

SELECT DISTINCT (`amount`) 
FROM cart 
ORDER BY CAST( `amount` AS SIGNED ) DESC 
LIMIT 4 , 1

여기서 N = 4를 입력하면 CART 테이블에서 5번째 최고 금액 기록을 얻을 수 있습니다.필드 및 테이블 이름에 맞게 솔루션을 제안할 수 있습니다.

Oracle:

select * from (select foo from bar order by foo) where ROWNUM = x

추가:

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번을 바꾸세요.

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번째 행의 정보가 반환됩니다.그 후에 반드시 rowcount 0을 입력해 주세요.

다음은 동적 페이징/소팅을 지원하는 Oracle용 spro의 일반 버전입니다(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);

하지만 실제로 이 모든 것이 애초에 좋은 데이터베이스 설계를 위한 단순한 속임수 아닌가요?이런 기능이 필요했던 적은 몇 번 있었습니다.단순한 오프 쿼리로 빠른 보고서를 작성했습니다.실제 업무에서 이런 속임수를 쓰는 것은 문제를 일으킨다.특정 행을 선택해야 하는 경우 순차 값이 포함된 열만 있으면 됩니다.

화려한 것도, 특별한 기능도 없어요 만약 당신이 나처럼 카제를 사용할 경우...

SELECT TOP 1 * FROM (
  SELECT TOP n * FROM <table>
  ORDER BY ID Desc
)
ORDER BY ID ASC

ID 열 또는 데이터 스탬프 열이 있으면 신뢰할 수 있습니다.

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;

LIMIT n,1은 MS SQL Server에서 작동하지 않습니다.이 구문을 지원하지 않는 유일한 주요 데이터베이스인 것 같습니다.SQL 표준에는 포함되어 있지 않습니다.단, SQL 표준에는 포함되어 있지 않습니다.SQL Server LIMIT을 제외한 모든 것이 정상적으로 동작합니다.SQL Server의 경우 우아한 솔루션을 찾을 수 없었습니다.

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
    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

여기 파티에는 조금 늦었지만 창가나 사용할 필요 없이 이 작업을 수행했습니다.

WHERE x IN (...)
SELECT TOP 1
--select the value needed from t1
[col2]
FROM
(
   SELECT TOP 2 --the Nth row, alter this to taste
   UE2.[col1],
   UE2.[col2],
   UE2.[date],
   UE2.[time],
   UE2.[UID]
   FROM
   [table1] AS UE2
   WHERE
   UE2.[col1] = ID --this is a subquery 
   AND
   UE2.[col2] IS NOT NULL
   ORDER BY
   UE2.[date] DESC, UE2.[time] DESC --sorting by date and time newest first
) AS t1
ORDER BY t1.[date] ASC, t1.[time] ASC --this reverses the order of the sort in t1

꽤 빨리 작동하는 것 같습니다만, 공정하게 말하면 500행 정도의 데이터밖에 없습니다.

이것은 MSQL로 동작합니다.

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
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;

이는 limit 구(SQLite에서는 LIMIT <recs to skip>, <recs to take>)의 서브쿼리를 사용할 수 있는가에 따라 달라집니다.테이블 내의 레코드 수는 데이터베이스의 메타데이터의 일부로서 특히 효율적입니다만, 데이터베이스의 실장에 따라 달라집니다.또, N번째 레코드를 취득하기 전에, 실제로 결과 세트를 작성할지는 모르지만, 그럴 필요는 없었으면 합니다."순서 기준" 절을 지정하는 것이 아닙니다.인덱스가 있는 기본 키와 같은 것을 "주문"하는 것이 더 나을 수 있습니다. 결과 세트를 구축하지 않고 데이터베이스가 데이터베이스 자체에서 N번째 레코드를 가져올 수 없는 경우 색인에서 N번째 레코드를 가져오는 것이 더 빠를 수 있습니다.

이 문서에서 본 SQL Server에 대한 가장 적절한 답변

WITH myTableWithRows AS (
    SELECT (ROW_NUMBER() OVER (ORDER BY myTable.SomeField)) as row,*
    FROM myTable)
SELECT * FROM myTableWithRows WHERE row = 3

네이티브 기능을 확인하는 경우:MySQL, Postgre실제로 NTH_VALUE 창 함수를 사용할 수 있습니다(기본적으로 SQL Server에는 이 기능이 없는 것 같습니다).Oracle 출처:Oracle 기능: NTH_VALUE

실제로 Oracle DB에서 첫 번째 행(주문 후)과 두 번째 행(주문 후)을 비교하기 위해 이 기능을 실험했습니다.코드는 다음과 같습니다(링크로 이동하지 않는 경우).

SELECT DISTINCT dept_id
     , NTH_VALUE(salary,2) OVER (PARTITION BY dept_id ORDER BY salary DESC
           RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS "SECOND HIGHEST"
     , NTH_VALUE(salary,3) OVER (PARTITION BY dept_id ORDER BY salary DESC
           RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
        AS "THIRD HIGHEST"
  FROM employees
 WHERE dept_id in (10,20)
 ORDER 
    BY dept_id;

나는 그것이 꽤 흥미롭다고 느꼈고 그들이 내가 그것을 사용하도록 해주었으면 좋겠다.

언급URL : https://stackoverflow.com/questions/16568/how-to-select-the-nth-row-in-a-sql-database-table

반응형