1

プレーン SQL を使用して結果セットからn番目に高い値を取得する最も簡単な方法は何ですか?

結果セットは膨大になるため、パフォーマンスも考慮する必要があります。

4

8 に答える 8

2

これは、以下を使用した T-SQL (SQL-Server 2005 以降) のアプローチROW_NUMBERです。

WITH CTE AS
(
   SELECT 
      Col1, Col2, ValueCol,
      RN = ROW_NUMBER() OVER (ORDER BY ValueCol DESC) -- change to ASC if you want lowest first
   FROM 
      dbo.TableName
)
SELECT 
   Col1, Col2, ValueCol
FROM 
   CTE
WHERE 
   RN = @nthhighestvalue

同じ値を持つすべての行が必要な場合は、DENSE RANK代わりに使用します。

ROW_NUMBER、RANK、DENSE_RANK の違い

于 2013-01-07T12:58:50.447 に答える
2

この記事では、この質問について詳しく説明しています。コードを以下に引用します。

解決策 1: N 番目に高い給与を見つけるこの SQL は、SQL Server、MySQL、DB2、Oracle、Teradata、およびその他のほぼすべての RDBMS で機能するはずです: (注: サブクエリのためパフォーマンスが低下します)

SELECT * /*This is the outer query part */
FROM Employee Emp1
WHERE (N-1) = ( /* Subquery starts here */
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary)

上記のクエリで理解しておくべき最も重要なことは、行が外側のクエリによって処理されるたびにサブクエリが評価されるということです。つまり、内側のクエリも Emp1 値を使用するため、内側のクエリを外側のクエリとは独立して処理することはできません。

N 番目に高い給与を見つけるには、それ自体よりちょうど N-1 高い給与を見つけるだけです。


解決策 2: SQL Server で TOP キーワードを使用して n 番目に高い給与を検索する

SELECT TOP 1 Salary
FROM (
      SELECT DISTINCT TOP N Salary
      FROM Employee
      ORDER BY Salary DESC
      ) AS Emp
ORDER BY Salary

解決策 3: TOP を使用せずに SQL Server で n 番目に高い給与を見つける

SELECT Salary FROM Employee 
ORDER BY Salary DESC OFFSET N-1 ROW(S) 
FETCH FIRST ROW ONLY

上記の SQL を個人的にテストしていないことに注意してください。SQL Server 2012 以降でのみ機能すると思います。


解決策 4: MySQL で動作する

SELECT Salary FROM Employee 
ORDER BY Salary DESC LIMIT n-1,1

LIMIT 句はそのクエリで 2 つの引数を取ります。最初の引数は返す最初の行のオフセットを指定し、2 番目の引数は返す行の最大数を指定します。


解決策 5: Oracle で動作する

select * from (
  select Emp.*, 
row_number() over (order by Salary DESC) rownumb 
from Employee Emp
)
where rownumb = n;  /*n is nth highest salary*/

解決策 6:オラクルの方法 2 で動作する

select * FROM (
select EmployeeID, Salary
,rank() over (order by Salary DESC) ranking
from Employee
)
WHERE ranking = N;
于 2014-02-05T18:08:06.397 に答える
0

5 番目に高い給与を見つけたいとしましょう。まず、最初の 5 つの個別の給与を降順で取得し、最後の給与が 5 番目に高い給与になるようにします (内部クエリを参照)。次に、それを昇順に並べ替えて、最初のものを取ります。

SELECT TOP 1 Salary FROM
(
  SELECT DISTINCT TOP 5 Salary
  FROM Employee
  ORDER BY Salary DESC)  t

ORDER BY  Salary ASC
于 2013-03-10T20:39:22.133 に答える
0

順序付けられた番号付きのデータセットを作成することから始めて、そこから選択します。正確な構文は RDBMS によって異なりますが、たとえば、Oracle では次のことができます。

SELECT ROWNUM, SOMEVAL
FROM (SELECT SOMEVAL FROM SOMETABLE ORDER BY SOMEVAL DESC)

上記のセットを考えると、次のことができます

SELECT SOMEVAL WHERE ROWNUM = :N
于 2013-01-07T13:01:37.480 に答える
0

オラクルの場合:

SELECT * FROM (
  SELECT col1, ROW_NUMBER()OVER(ORDER BY col1) rnum_col1 FROM table1
) WHERE rnum_col1 = 10;
于 2013-01-07T19:58:23.523 に答える
0

一般的なデータベースでは、サブクエリと 2 つの でこれを行うことができますorder by。問題は、top/limit/rownum 構文が標準ではないことです。一部のデータベースでは、次のように記述します。

于 2013-01-07T14:21:16.153 に答える
0

サブクエリは、上位 'n' 個の最高給与値を一覧表示します。そのリストの最小値は、n 番目に高い給与になります。

`SELECT min(salary) FROM
    (SELECT DISTINCT TOP n salary FROM EmployeeTable ORDER BY salary desc);`

例:- 3 番目の最高給与を検索する SQL クエリ

`SELECT min(salary) FROM
    (SELECT DISTINCT TOP 3 salary FROM EmployeeTable ORDER BY salary desc);`
于 2020-07-14T05:42:07.713 に答える
-1

並べ替えのオーバーヘッドが発生する必要があります。私の例rownumでは、物理的な場所ではなく、並べ替えられた行番号です。

誰もが分析関数を使用してこれがどのように機能するかを示しているため、ここにその 1 つを示します。

   select foo,bar, max(baz)  
    from  
    (
       select *   
      from  
      (  
          select foo,bar,baz, row_number() over 
          (partition by some_identifier_that_Groups order by  value DESC) rn 
      )    
       where rn = 1  -- get the highest value for each partition    
    ) group by foo,bar
于 2013-01-07T12:57:38.603 に答える