各部門に3人の従業員がいるとします。合計3つの部門があります。以下はサンプルソーステーブルです
Emp deptno salary
A 10 1000
B 10 2000
C 10 3000
D 20 7000
E 20 9000
F 20 8000
G 30 17000
H 30 15000
I 30 30000
出力
B 10 2000
F 20 8000
G 30 17000
分析関数dense_rankを使用すると、部門ごとに2番目に高い給与を達成できます。
分析関数を使用せずにこれを達成できますか?
Max()も分析関数ですか?
それは苦痛ですが、あなたはそれを行うことができます。次のクエリは、2番目に高い給与を取得します。
select t.deptno, max(t.salary) as maxs
from table t
where t.salary < (select max(salary)
from table t2
where t2.deptno = t.deptno
)
group by t.deptno;
次に、これを使用して従業員を取得できます。
select t.*
from table t join
(select t.deptno, max(t.salary) as maxs
from table t
where t.salary < (select max(salary)
from table t2
where t2.deptno = t.deptno
)
group by t.deptno
) tt
on t.deptno = tt.deptno and t.salary = tt.maxs;
これにより、各部門で2番目に高い給与が得られます。
SELECT a.Emp, a.deptno, a.salary
FROM Emp a
WHERE 1 = (SELECT COUNT(DISTINCT salary)
FROM Emp b
WHERE b.salary > a.salary AND a.deptno = b.deptno)
group by a.deptno
テーブルを作成してダミーデータを挿入
CREATE TABLE #Employee
(
Id Int,
Name NVARCHAR(10),
Sal int,
deptId int
)
INSERT INTO #Employee VALUES
(1, 'Ashish',1000,1),
(2,'Gayle',3000,1),
(3, 'Salman',2000,2),
(4,'Prem',44000,2)
結果を取得するためのクエリ
;WITH cteRowNum AS (
SELECT *,
DENSE_RANK() OVER(PARTITION BY deptId ORDER BY Sal DESC) AS RowNum
FROM #Employee
)
SELECT *
FROM cteRowNum
WHERE RowNum = 2;
次のような2番目に高い給与を見つけることができます。
select max(a.Salary),a.Deptno from Employee a join (select MAX(salary) salary
from Employee group by Deptno) b on a.Salary < b.salary group by a.Deptno
また、MAX()は分析関数ではありません。
非常に単純で宣言的ですが、遅い
select
t1.*
from
#tmp t1
inner join #tmp h1 on h1.dept = t1.dept and h1.emp <> t1.emp
left outer join #tmp h2 on h2.dept = h1.dept and h2.salary > h1.salary
left outer join #tmp t2 on t1.dept = t2.dept and t2.salary > t1.salary and t2.emp <> h1.emp
where
t2.emp is null and h2.emp is null
MySQLでは、テーブル名がsalariesの場合、2番目に高い給与を取得する方法は次のとおりです。
ネストされたクエリ別:(オフセット0/1/2をそれぞれ1位、2位、3位に変更できます)
select
*
from
salaries as t1
where
t1.salary = (select
salary
from
salaries
where
salaries.deptno = t1.deptno ORDER by salary desc limit 1 offset 1);
または、ランクを作成することもできます:(ランク= 1/2/3をそれぞれ1位、2位、3位に変更できます)
SET @prev_value = NULL;
SET @rank_count = 0;
select * from
(SELECT
s.*,
CASE
WHEN @prev_value = deptno THEN @rank_count := @rank_count + 1
WHEN @prev_value := deptno THEN @rank_count := 1
ELSE @rank_count := 1
END as rank
FROM salaries s
ORDER BY deptno, salary desc) as t
having t.rank = 2;