8

分析関数の操作は初めてです。

部門EMPの給与
---- ----- ------
  10 メアリー 100000
  10 ジョン 200000
  10 スコット 300000
  20 ボブ 100000
  20 ベティ 200000
  30 アラン 100000
  30 トム 200000
  30 ジェフ 300000

最低給与の部門と従業員が必要です。

結果は次のようになります。

部門EMPの給与
---- ----- ------
  10 メアリー 100000
  20 ボブ 100000
  30 アラン 100000

編集:これが私が持っているSQLです(もちろん、group by句にもスタッフが必要なため、機能しません):

選択部門、
  従業員、
  MIN(給与) KEEP (給与によるDENSE_RANK FIRST ORDER)
FROM マイテーブル
GROUP BY 部門
4

4 に答える 4

10

2つの理由から、Rank()関数はこれを実行する方法ではないと思います。

まず、Min()ベースのメソッドよりも効率が悪い可能性があります。

これは、クエリがデータをスキャンするときに部門ごとのすべての給与の順序付きリストを維持する必要があるためです。その後、このリストを再度読み取ることにより、ランクが割り当てられます。明らかに、これに利用できるインデックスがない場合、最後のデータ項目が読み取られるまでランクを割り当てることができず、リストの保守に費用がかかります。

したがって、Rank()関数のパフォーマンスは、スキャンされる要素の総数に依存します。その数が、ソートがディスクに流出するのに十分な場合、パフォーマンスは低下します。

これはおそらくより効率的です:

select dept,
       emp,
       salary
from
       (
       SELECT dept, 
              emp,
              salary,
              Min(salary) Over (Partition By dept) min_salary
       FROM   mytable
       )
where salary = min_salary
/

この方法では、クエリがこれまでに遭遇した最小値の部門ごとに1つの値を維持する必要があるだけです。新しい最小値が検出されると、既存の値が変更されます。それ以外の場合、新しい値は破棄されます。メモリに保持する必要のある要素の総数は、スキャンされた行の数ではなく、部門の数に関連しています。

この場合、ランクを実際に計算する必要がないことを認識するためのコードパスがOracleにある可能性がありますが、私はそれには賭けません。

Rank()を嫌う2つ目の理由は、間違った質問に答えるだけだからです。問題は、「部門ごとの給与が昇順の場合に最初にランク付けされる給与を持つレコード」ではなく、「部門ごとの最低給与を持つレコード」です。少なくとも、それは私にとって大きな違いになります。

于 2009-10-08T07:06:55.840 に答える
5

元のクエリにかなり近いと思います。以下が実行され、テスト ケースと一致します。

SELECT dept, 
  MIN(emp) KEEP(DENSE_RANK FIRST ORDER BY salary, ROWID) AS emp,
  MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY salary, ROWID) AS salary
FROM mytable
GROUP BY dept

RANK() ソリューションとは対照的に、これは部門ごとに最大で 1 つの行を保証します。しかし、これは問題を暗示しています。最低賃金の従業員が 2 人いる部門ではどうなるでしょうか。RANK() ソリューションは両方の従業員を返します。つまり、部門の複数の行です。この回答は、任意に 1 つを選択し、部門に 1 つだけであることを確認します。

于 2009-10-09T06:30:13.930 に答える
3

構文を使用できRANK()ます。たとえば、このクエリは、給与の額に関して、従業員が部門内のどこにランク付けされているかを示します。

SELECT
  dept,
  emp,
  salary,
  (RANK() OVER (PARTITION BY dept ORDER BY salary)) salary_rank_within_dept
FROM EMPLOYEES

次に、これからクエリを実行できますsalary_rank_within_dept = 1

SELECT * FROM
  (
    SELECT
      dept,
      emp,
      salary,
      (RANK() OVER (PARTITION BY dept ORDER BY salary)) salary_rank_within_dept
    FROM EMPLOYEES
  )
WHERE salary_rank_within_dept = 1
于 2009-10-07T18:09:31.657 に答える
-1
select e2.dept, e2.emp, e2.salary
from employee e2
where e2.salary = (select min(e1.salary) from employee e1)
于 2009-10-07T18:10:46.533 に答える