【SQLブッチャーシリーズ】leetcode-176.2番目に高い給料

ここに画像の説明を挿入

今日のプログラマーの面接プロセスでは、SQL のいくつかの能力を調べることは難しくありませんが、ほぼ必須です.
思考の盲点をチェックし、転覆を避けるために、レビューを確認することもできます.よろしくお願いします〜
ps: データ開発者の皆様、ご自身で調査の難易度を上げることをお勧めします

リートコード難易度:中
面接頻度:中

1.トピックス

1.1 表

従業員テーブル:

+-------------+------+
| Column Name | Type |
+-------------+------+
| id          | int  |
| salary      | int  |
+-------------+------+
id 是这个表的主键。
表的每一行包含员工的工资信息。

1.2 要件

Employee テーブルで 2 番目に高い給与を取得して返す SQL クエリを作成します。2 番目に高い給与が存在しない場合、クエリは null を返す必要があります。

クエリの結果を次の例に示します。

输入:
Employee 表:
+----+--------+
| id | salary |
+----+--------+
| 1  | 100    |
| 2  | 200    |
| 3  | 300    |
+----+--------+
输出:
+---------------------+
| SecondHighestSalary |
+---------------------+
| 200                 |
+---------------------+

输入:
Employee 表:
+----+--------+
| id | salary |
+----+--------+
| 1  | 100    |
+----+--------+
输出:
+---------------------+
| SecondHighestSalary |
+---------------------+
| null                |
+---------------------+

2. 試験場分析

第 1 レベルのソリューション

この質問は非常に簡単です. 主にソート + リミット + オフセットの適用について調べます. 多くの初心者はオフセット OFFSET に慣れていない可能性があり、開始するのが難しい.

2番目の解決策

合格

第 3 レベルのソリューション

合格

より多くのアイデア

3. 開く

1. 溶液の最初の層

limit n 句は、クエリ結果が最初の n 個のデータを返すことを
意味します offset n は x ステートメントをスキップすることを意味します limit y オフセット x 句は、クエリ結果が x 個のデータをスキップし、 limit と offset を使用し
て最初の y 個のデータを読み取ることを意味します
、降順にソートして返す 2 番目のレコードは 2 番目に大きい値を取得できます。

SELECT
    IFNULL(
      (SELECT DISTINCT Salary
       FROM Employee
       ORDER BY Salary DESC
        LIMIT 1 OFFSET 1),
    NULL) AS SecondHighestSalary

PS: sql の堅牢性に注意してください。IFNULL の null 値の判断を忘れないでください。

4. 拡張: N 番目に高い給与

Employee テーブルで n 番目に高い給与を報告する SQL クエリを記述します。n 番目に高い給与がない場合、クエリは null を報告する必要があります。

输入: 
Employee table:
+----+--------+
| id | salary |
+----+--------+
| 1  | 100    |
| 2  | 200    |
| 3  | 300    |
+----+--------+
n = 2
输出: 
+------------------------+
| getNthHighestSalary(2) |
+------------------------+
| 200                    |
+------------------------+

输入: 
Employee 表:
+----+--------+
| id | salary |
+----+--------+
| 1  | 100    |
+----+--------+
n = 2
输出: 
+------------------------+
| getNthHighestSalary(2) |
+------------------------+
| null                   |
+------------------------+

4.1 説明

ランキングはデータベースの古典的なトピックであり、ランキングの具体的な詳細に応じて 3 つのシナリオに分けることができます。

年俸3000、2000、2000、1000などの連続順位、順位結果は1-2-3-4、同じ年俸で名前が違うことを反映、数字
と同じ年俸で名前が同じでも順位は似ているが、同一給与分布、順位結果など総合順位が連続しない同一
給与同一名義で1-2-2-4となり総合順位が連続し同一給与順位結果が1-2となる-2-3
アプリケーション シナリオが異なれば、異なるランキング結果が必要になる場合があります。これは、クエリ戦略も異なることを意味します。この質問の目標は、第 3 のランキング方式で N 番目の結果を達成することであり、グローバル ランキングであり、グループ化の問題はなく、実際には比較的単純です。

Oracle などのデータベースにはこれらの要件を簡単に実装できるウィンドウ関数があり、MySQL もバージョン 8.0 まで関連する関数を導入したことは特筆に値します。最新のOJ環境をバージョン8.0にアップデートし、ウィンドウ機能をそのまま利用できるようになりました。

4.2 アイデア

最も単純なタイプの質問は、ウィンドウ関数を使用してプレイすることです。もちろん、自分自身に挑戦したい場合は、より多くのソリューションを使用してプレイできます。

4.3 窓関数の解法

実際、mysql8.0 には関連する組み込み関数があり、さまざまなランキングの問題が考慮されています。

  • row_number(): 給与は同じですが、名前が異なります。行番号に相当します。たとえば、3000、2000、2000、1000 は 1、2、3、4 としてランク付けされます。
  • rank(): 同じ給与と同じ名前、スキップ レベル (たとえば、3000、2000、2000、1000) は 1、2、2、4 としてランク付けされます。
  • Dens_rank(): 3000位、2000位、2000位、1000位以降、同じ給料で同名、飛び跳ねなし
  • ntile(): バケットのランキング、つまり、最初、1 番目、2 番目、3 番目のバケットをバケットの数に応じて分割し、各バケットを 1 からランク付けしますが、これは実際にはあまり一般的ではありません。

明らかに、この問題は 3 番目の関数を使用することです。
さらに、これら 3 つの関数は、パートナーである over() と一緒に使用する必要があります。over() には 2 つの共通パラメーターがあります。

  • 分割、フィールドによる分割
  • order by は、通常の order by の使用法と一致しており、ASC (デフォルト) と DESC も区別します.これは、ランキングの基準が必要であるためです.
    注: 次のコードは、mysql8.0 以降、および最新のOJ がサポートされました。
        SELECT 
            DISTINCT salary
        FROM 
            (SELECT 
                salary, dense_rank() over(ORDER BY salary DESC) AS rnk
             FROM 
                employee) tmp
        WHERE rnk = N


手術

ランキングの問題に対するより良い解決策はありますか?


ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_31557939/article/details/126697436