記事ディレクトリ
今日のプログラマーの面接プロセスでは、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
手術
ランキングの問題に対するより良い解決策はありますか?