سؤال

وأنا جديدة على العمل مع الدوال التحليلية.

DEPT EMP   SALARY
---- ----- ------
  10 MARY  100000
  10 JOHN  200000
  10 SCOTT 300000
  20 BOB   100000
  20 BETTY 200000
  30 ALAN  100000
  30 TOM   200000
  30 JEFF  300000

وأريد القسم والموظف مع الحد الأدنى للأجور.

ونتائج يجب أن تبدو:

DEPT EMP   SALARY
---- ----- ------
  10 MARY  100000
  20 BOB   100000
  30 ALAN  100000

وتحرير: وهنا يكمن SQL لدي (ولكن بطبيعة الحال، فإنه لا عمل لأنه يريد الموظفين في مجموعة من بند كذلك):

SELECT dept, 
  emp,
  MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY salary)
FROM mytable
GROUP BY dept
هل كانت مفيدة؟

المحلول

وأعتقد أن وظيفة الرتبة () ليست وسيلة للذهاب مع هذا، وذلك لسببين.

أولا، وربما هو أقل كفاءة من (الحد) - طريقة استنادا

والسبب في ذلك هو أن الاستعلام ديه للحفاظ على قائمة مرتبة من جميع الرواتب لكل قسم كما تقوم بمسح البيانات، وبعد ذلك سوف يتم تعيين رتبة في وقت لاحق من هذه القائمة القراءة من جديد. من الواضح في حالة عدم وجود الفهارس التي يمكن الاستفادة لهذا، لا يمكنك تعيين مرتبة حتى تمت قراءة عنصر البيانات الماضي، وصيانة قائمة مكلفة.

وهكذا أداء رتبة () وظيفة تعتمد على عدد من العناصر التي يتم مسحها ضوئيا، وإذا كان الرقم كافية على أن هذا النوع يمتد إلى القرص ثم سوف تنهار الأداء.

وهذا هو على الارجح أكثر كفاءة:

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

وهذه الطريقة تتطلب فقط أن الاستعلام الحفاظ على قيمة واحدة لكل قسم من الحد الأدنى للقيمة التي تواجهها حتى الآن. وإذا تم مصادفة ثم يتم تعديل الحد الأدنى الجديد للقيمة الحالية، وإلا يتم تجاهل القيمة الجديدة. يرتبط العدد الإجمالي للعناصر التي ستعقد في الذاكرة إلى عدد من الإدارات، تفحص ليس عدد الصفوف.

وكان من الممكن أن يكون هذا أوراكل لديها مسار رمز للاعتراف بأن الرتبة لا تحتاج حقا أن تحسب في هذه الحالة، ولكن أود أن لا تراهن على ذلك.

والسبب الثاني لالكره الرتبة () هو أنه مجرد يجيب على السؤال الخطأ. المسألة ليست "أي سجلات يكون الراتب الذي هو أول مرتبة عندما رواتب لكل قسم وتصاعدي أمر"، فمن "أي سجلات يكون الراتب الذي هو الحد الأدنى لكل قسم". أن يحدث فرقا كبيرا بالنسبة لي، على الأقل.

نصائح أخرى

واعتقد انكم كانت قريبة جميلة مع الاستعلام الأصلي. ان يلي تشغيل والقيام تطابق حالة اختبار الخاص بك:

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 () الحلول، هذا واحد ضمانات في معظم صف واحد لكل قسم. ولكن هذا يلمح إلى مشكلة: ما يحدث في قسم حيث هناك اثنين من الموظفين على الراتب الأدنى؟ والحلول RANK () ترجع كلا الموظفين - أكثر من صف واحد للدائرة. وهذا الجواب اختيار واحد تعسفا وتأكد من هناك واحد فقط للإدارة.

ويمكنك استخدام بناء الجملة 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
select e2.dept, e2.emp, e2.salary
from employee e2
where e2.salary = (select min(e1.salary) from employee e1)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top