وظيفة أوراكل تحليلية لقيمة دقيقة في التجمع
-
20-09-2019 - |
سؤال
وأنا جديدة على العمل مع الدوال التحليلية.
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)