目次
1. 部門内の上位 3 位の給与を持つ全従業員 (185)
表面: Employee
+--------------+-----------+ | 列名 | タイプ | +-------------+-- - ------+ | id | int | | |DepartmentId | |給与 | int | name | varchar | Id はテーブルの主キー列です。 planId は、Department テーブルの ID への外部キーです。 このテーブルの各行は、従業員の ID、名前、給与を表します。部門の ID も含まれます。
表面: Department
+-------------+--------+ | 列名 | タイプ | +-------------+---- ----------+ | id | int | | name | varchar | +-------------+---------+ Id はテーブルの主キー列です。 このテーブルの各行は、部門 ID と部門名を表します。
会社の重役は、会社の各部門で誰が一番お金を稼いでいるかに興味を持っています。部門の 高所得者と は、従業員の給与が その部門内のさまざまな 給与 の中でトップ 3 にランクされる場合です 。
SQL クエリを作成して、 各部門の高給取りの従業員を検索します 。
結果テーブルを任意の順序で 返します 。
解決策 1 (dense_rank() ウィンドウ関数)
Density_rank() ソート ルール 1 2 3 3 4
ランク() 1 2 3 3 5
フィールドに従ってパーティションごとに分割する
# Write your MySQL query statement below
select Department, Employee, Salary
from (select d.name Department,e.name Employee,e.salary Salary ,dense_rank() over(partition by d.name order by e.salary desc) no from employee e join department d
on e.departmentId=d.id) temp
where temp.no<=3
解決策 2 (カスタム関数)
私はまだこのカスタム関数の使い方に少し慣れただけですが、このカスタム関数の登場により SQL がより柔軟になる可能性があります。
CASE
WHEN @pre =DepartmentId THEN @rank:= @rank + 1
WHEN @pre :=DepartmentId THEN @rank:= 1
END AS 'RANK'
これは、@pre が現在のDepartmentId と等しい場合は @rank に 1 を追加し、それ以外の場合は @pre および @rank=1 の値を更新することを意味します。
この @rank の値は、RANK フィールドと呼ばれます。これを使用して並べ替える鍵となるのは、from テーブルが順序どおりである必要があるということです。
SELECT dep.Name Department, emp.Name Employee, emp.Salary
FROM (## 自定义变量RANK, 查找出 每个部门工资前三的排名
SELECT te.DepartmentId, te.Salary,
CASE
WHEN @pre = DepartmentId THEN @rank:= @rank + 1
WHEN @pre := DepartmentId THEN @rank:= 1
END AS 'RANK'
FROM (SELECT @pre:=null, @rank:=0)tt,
(## (部门,薪水)去重,根据 部门(升),薪水(降) 排序
SELECT DepartmentId,Salary
FROM Employee
GROUP BY DepartmentId,Salary
ORDER BY DepartmentId,Salary DESC
)te
)t
INNER JOIN Department dep ON t.DepartmentId = dep.Id
INNER JOIN Employee emp ON t.DepartmentId = emp.DepartmentId and t.Salary = emp.Salary and t.RANK <= 3
ORDER BY t.DepartmentId, t.Salary DESC ## t 结果集已有序,根据该集合排序
2. 重複したメールアドレスを削除する(196)
表面: Person
+-------------+--------+ | 列名 | タイプ | +-------------+---- ----------+ | id | int | | email | varchar | +-------------+---------+ id はテーブルの主キー列です。 このテーブルの各行には電子メールが含まれます。メールには大文字を含めることはできません。
SQL 削除ステートメントを作成して、 重複する電子メールをすべて削除し 、最小 ID を持つ一意の電子メールを 1 つだけ保持します。
結果テーブルを任意の順序で 返します 。(注: delete ステートメントを記述するだけで済み、残りの結果は自動的にクエリされます)
解決策 1
まずは逆向きに考えて不満点を見つけます。グループ分けに応じて簡単に見つかります
DELETE from Person
WHERE id NOT IN #不在满足条件内的肯定就是不满足的,直接删除
(
SELECT ID #先把满足条件的找出来
From
(
SELECT MIN(id) as ID
From Person
Group by Email
)t
)
解決策 2 (公式分析)
# Write your MySQL query statement below
DELETE p1 FROM Person p1,
Person p2
WHERE
p1.Email = p2.Email AND p1.Id > p2.Id
3. 温度上昇(197)
表面: Weather
+--------------+--------+ | 列名 | タイプ | +---------------+ --------+ | id | int | | | 温度 | RecordDate | date | id は 、特定の日付の温度情報を含む このテーブルの主キーです。
SQL クエリを作成して、前回 (昨日) の日付よりも気温が高い日付をすべて検索します id
。
返される結果には 順序は必要ありません 。
例 1:
输入:
Weather 表:
+----+-----------+-------------+
| id | 記録日 | 温度 |
+----+---- --------+-------------+
| 1 | 2015-01-01 | 10 |
| 2 | 2015-01-02 | 25 |
| 3 | 2015- 01-03 | 20 |
| 4 | 2015-01-04 | 30 |
+----+------------+-----------+出力:
+----+
| id |
+----+
| 2 |
| 4 |
+----+説明:
2015-01-02 の気温は前日よりも高くなります (10 -> 25) )
2015-01-04 気温は前日より高かった (20 -> 30)
解決策 1 (DATEDIFF())
DATEDIFF 関数。2 つの日付の差を計算できます。
DATEDIFF('2007-12-31','2007-12-30'); #1
DATEDIFF('2010-12-30','2010-12-31'); # -1
# Write your MySQL query statement below
select a.ID
from weather as a cross join weather as b
on datediff(a.recordDate, b.recordDate) = 1
where a.temperature > b.temperature;
解決策 2 (TIMESTAMPDIFF())
TIMESTAMPDIFF でできることは、日、時、分、秒の差を計算することで、datediff 関数よりもはるかに柔軟です。前のタイムが小さく、後ろのタイムが大きいという形式です。日数の差を計算する
select a.ID
from weather as a cross join weather as b
on timestampdiff(day,a.recordDate, b.recordDate) = -1
where a.temperature > b.temperature;
解決策 3 (ADDDATE()ボタン)
select a.id
from weather a join weather b
on (a.recorddate = adddate(b.recorddate,INTERVAL 1 day))
where a.temperature > b.temperature