leetcode力扣データベースSQLテーマと解答(三)
11518 ワード
今日の目標はやはり難題と簡単な問題の組み合わせで拳を出して、引き継ぎました!くだらないことは言わないで、始めましょう.
文書ディレクトリ 185. 部門給与上位3社全員(困難) 構想1:自己接続 構想2:開窓関数 196.重複するメールボックスを削除(単純) 考え方1:マルチテーブル削除 考え方2:削除+NOT IN 182.重複するメールボックスの検索(簡単) 181.マネージャの収入を超える従業員(単純) 183.注文しないお客様(単純) 構想1:not in 構想2:is null 185.部門給与の上位3社のすべての従業員(困難)
経典のTOP N問題の解法;難易度が少し高くなれば、グループ内のトップNを獲得することもできますよ.超定番タイトル!!!
Employeeテーブルには、すべての従業員情報が含まれています.各従業員には、対応する労働番号Id、名前Name、給与Salary、部門番号DepartmentIdがあります.
Id
Name
Salary
DepartmentId
1
Joe
85000
1
2
Henry
80000
2
3
Sam
60000
2
4
Max
90000
1
5
Janet
69000
1
6
Randy
85000
1
7
Will
70000
1
Departmentテーブルには、会社のすべての部門の情報が含まれています.
Id
Name
1
IT
2
Sales
SQLクエリーを作成し、各部門で上位3位の給料をもらったすべての従業員を見つけます.たとえば、上記で指定したテーブルに基づいて、クエリの結果は次のように返されます.
Department
Employee
Salary
IT
Max
90000
IT
Randy
85000
IT
Joe
85000
IT
Will
70000
Sales
Henry
80000
Sales
Sam
60000
説明:
IT部門ではMaxが最高賃金を獲得し、RandyもJoeも2番目に高い賃金を獲得し、Willの賃金は3位だった.販売部門(Sales)には従業員が2人しかいないが、Henryの給料が最も高く、Samの給料は2位だ.
問題:
構想1:自己接続
このようなパケット内で上位N名を取る問題については、groupbyを先にグループ化し、having count()でフィルタリングすることができる.例えば、この問題では、各部門の給料の上位3位を探して、サブクエリでEmployeeで自分と接続し、接続条件は「部門は同じだが給料は私より高い」で、次にhaving count(Salary)<=3に従って選別する原理は、「私と同じ部門で給料が私より高い人数」が3つを超えなければ、私は部門の給料の上位3位に違いない.これにより、内層クエリーでは、要件に合致するすべての従業員IDをクエリーでき、その後、外層クエリーが簡単になります.
エラーポイント:グループ:必ずグループbyを加えなければなりません.このテーマの要求は各部門のTOP 3を得ることですから、グループがなければ、最終的な結果は全体のTOP 3ではないでしょうか. 順序:私は自己反省して、意外にも順序を書き間違えて、正しい順序はgroup by-having-order by~であるべきですが、私はこの3つのキーワードの順序を覚える良い方法を考えました:byの両側を歩いて、havingは真ん中にあります.ほら、対称ですね.次は絶対に間違いを犯しません. カウント:表2の給与>表1の給与であるため、表1の各行のレコードについては、表2のいずれにおいてもN行が表1より大きいレコードが存在するので、ここではランキング を得るためにcount(表2)すべきである.
考え方2:開窓関数
開窓関数を使用してランキングを取得します(SqlServer、Orcalなど開窓関数をサポートするデータベースにのみ適用されます.MySQL環境では開窓関数は使用できません).
196.重複するメールボックスを削除する(簡単)
題名:deleteの使い方を考察して1つのテーブルを削除したり、複数のテーブルを削除したりする場合
考え方1:マルチテーブル削除
eg 1:どのテーブルを削除するかを指定する必要がないテーブルがあります–DELETE FROM person WHERE id=3 eg 2:どのテーブルを削除するかを指定するテーブルが2つあります
考え方2:削除+NOT IN
まずemailに基づいてグループ化し、Idの最小保存を見つけます.テーブルを削除するときはIdを上記の範囲内にしないようにするだけです
182.重複するメールボックスの検索(簡単)
SQLクエリーを作成し、Personテーブルの重複するすべての電子メールボックスを検索します.
标题:考察group by+having(パケット後フィルタリング)メールボックスに従ってパケット化し、パケット化後havingを用いて個数>=2のメールボックスをフィルタリングする
181.マネージャーの収入を超えた従業員(簡単)
Employeeテーブルには、すべての従業員が含まれており、マネージャも従業員に属しています.各従業員にはIdがあり、従業員に対応するマネージャのIdの列もあります.
Employeeテーブルを指定して、SQLクエリーを作成します.このクエリーは、マネージャよりも収益の高い従業員の名前を取得できます.上の表では、Joeはマネージャーを上回る収入を持つ唯一の従業員です.問題解:考察自己接続はjoin自己接続を用い,e 1は従業員表,e 2は対応する部門主管表である.それから表1の給料>表2の給料でいいです.
183.注文しないお客様(簡単)
Webサイトには、2つのテーブル、Customersテーブル、Ordersテーブルがあります.SQLクエリーを作成し、何も注文していないすべてのお客様を見つけます.
考え方1:not in
まず注文表に購入記録のあるユーザーIdを見つけて、それからすべてのユーザーの中で選別して、これらの購入した商品のユーザーを排除して、残りは買い物をしたことがないユーザーです!
考え方2:is null
お客様が消費記録を持っている場合は、必ずOrdersテーブルに一致します.そうでない場合は、Ordersテーブル対応はnullとなります.これが左接続です.素晴らしいですね.
エラーポイント:nullフィールドかどうかを判断するには、等しい番号ではなくis nullまたはis not nullを使用します.
文書ディレクトリ
経典のTOP N問題の解法;難易度が少し高くなれば、グループ内のトップNを獲得することもできますよ.超定番タイトル!!!
Employeeテーブルには、すべての従業員情報が含まれています.各従業員には、対応する労働番号Id、名前Name、給与Salary、部門番号DepartmentIdがあります.
Id
Name
Salary
DepartmentId
1
Joe
85000
1
2
Henry
80000
2
3
Sam
60000
2
4
Max
90000
1
5
Janet
69000
1
6
Randy
85000
1
7
Will
70000
1
Departmentテーブルには、会社のすべての部門の情報が含まれています.
Id
Name
1
IT
2
Sales
SQLクエリーを作成し、各部門で上位3位の給料をもらったすべての従業員を見つけます.たとえば、上記で指定したテーブルに基づいて、クエリの結果は次のように返されます.
Department
Employee
Salary
IT
Max
90000
IT
Randy
85000
IT
Joe
85000
IT
Will
70000
Sales
Henry
80000
Sales
Sam
60000
説明:
IT部門ではMaxが最高賃金を獲得し、RandyもJoeも2番目に高い賃金を獲得し、Willの賃金は3位だった.販売部門(Sales)には従業員が2人しかいないが、Henryの給料が最も高く、Samの給料は2位だ.
問題:
構想1:自己接続
このようなパケット内で上位N名を取る問題については、groupbyを先にグループ化し、having count()でフィルタリングすることができる.例えば、この問題では、各部門の給料の上位3位を探して、サブクエリでEmployeeで自分と接続し、接続条件は「部門は同じだが給料は私より高い」で、次にhaving count(Salary)<=3に従って選別する原理は、「私と同じ部門で給料が私より高い人数」が3つを超えなければ、私は部門の給料の上位3位に違いない.これにより、内層クエリーでは、要件に合致するすべての従業員IDをクエリーでき、その後、外層クエリーが簡単になります.
select de.Name as Department,t.Name as Employee, t.Salary as Salary
from
(
select e1.Name,e1.Salary,e1.DepartmentId
from Employee e1 left join Employee e2
on e1.DepartmentId = e2.DepartmentId
and e1.Salary <= e2.Salary
group by e1.Name
having count(distinct e2.Salary)<=3
order by e1.Salary desc
) as t
join Department as de
on t.DepartmentId = de.Id
order by de.Name asc,t.Salary desc
エラーポイント:
考え方2:開窓関数
開窓関数を使用してランキングを取得します(SqlServer、Orcalなど開窓関数をサポートするデータベースにのみ適用されます.MySQL環境では開窓関数は使用できません).
select de.Name as Department,t.Name as Employee,t.Salary as Salary
from
(
select Name,Salary,DepartmentId,
dense_rank() over(partition by DepartmentId order by Salary desc) as rk
from Employee
) t
join Department de
on t.DepartmentId = de.Id
where t.rk<=3
196.重複するメールボックスを削除する(簡単)
題名:deleteの使い方を考察して1つのテーブルを削除したり、複数のテーブルを削除したりする場合
考え方1:マルチテーブル削除
eg 1:どのテーブルを削除するかを指定する必要がないテーブルがあります–DELETE FROM person WHERE id=3 eg 2:どのテーブルを削除するかを指定するテーブルが2つあります
delete p1
from Person p1 join Person p2
on p1.email = p2.email and p1.id>p2.id
考え方2:削除+NOT IN
まずemailに基づいてグループ化し、Idの最小保存を見つけます.テーブルを削除するときはIdを上記の範囲内にしないようにするだけです
delete from Person
where Id not in
(select t.id from
# , mysql select
# You can't specify target table 'Person' for update in FROM clause
(select min(Id) as id from Person
group by Email
) AS t
)
182.重複するメールボックスの検索(簡単)
SQLクエリーを作成し、Personテーブルの重複するすべての電子メールボックスを検索します.
标题:考察group by+having(パケット後フィルタリング)メールボックスに従ってパケット化し、パケット化後havingを用いて個数>=2のメールボックスをフィルタリングする
select Email from Person
group by Email
having count(Email)>=2
181.マネージャーの収入を超えた従業員(簡単)
Employeeテーブルには、すべての従業員が含まれており、マネージャも従業員に属しています.各従業員にはIdがあり、従業員に対応するマネージャのIdの列もあります.
Employeeテーブルを指定して、SQLクエリーを作成します.このクエリーは、マネージャよりも収益の高い従業員の名前を取得できます.上の表では、Joeはマネージャーを上回る収入を持つ唯一の従業員です.問題解:考察自己接続はjoin自己接続を用い,e 1は従業員表,e 2は対応する部門主管表である.それから表1の給料>表2の給料でいいです.
select e1.Name AS Employee
from Employee as e1
join Employee as e2 # join
on e2.Id = e1.ManagerId
where e1.Salary > e2.Salary
183.注文しないお客様(簡単)
Webサイトには、2つのテーブル、Customersテーブル、Ordersテーブルがあります.SQLクエリーを作成し、何も注文していないすべてのお客様を見つけます.
考え方1:not in
まず注文表に購入記録のあるユーザーIdを見つけて、それからすべてのユーザーの中で選別して、これらの購入した商品のユーザーを排除して、残りは買い物をしたことがないユーザーです!
select Name as Customers
from Customers where Id not in
(select CustomerId from Orders)
考え方2:is null
お客様が消費記録を持っている場合は、必ずOrdersテーブルに一致します.そうでない場合は、Ordersテーブル対応はnullとなります.これが左接続です.素晴らしいですね.
select c.Name as Customers
from Customers c
left join Orders o
on c.Id = o.CustomerId
where o.CustomerId is null
エラーポイント:nullフィールドかどうかを判断するには、等しい番号ではなくis nullまたはis not nullを使用します.