حقول إضافية مع SQL MIN () & Group by
-
05-09-2019 - |
سؤال
عند استخدام دالة SQL Min ()، إلى جانب المجموعة من خلال، هل سيتم مطابقة أي أعمدة إضافية (وليس عمود مين، أو أحد المجموعات حسب الأعمدة) البيانات الموجودة في صف Min Coll؟
على سبيل المثال، بالنظر إلى جدول مع أسماء القسم وأسماء الموظفين والراتب:
SELECT MIN(e.salary), e.* FROM employee e GROUP BY department
من الواضح أنني سأحصل على عمودين جيدين، الحد الأدنى للراتب والإدارة. هل سيكون اسم الموظف (وأي مجالات موظف أخرى) من نفس الصف؟ أي الصف مع الدقم (الراتب)؟
وأنا أعلم أنه يمكن أن يكون هناك اثنين من الموظفين مع نفس الراتب (والأدنى)، ولكن كل ما أنا مهتم به (الآن) هو الحصول على جميع المعلومات حول (أو واحد) أرخص الموظف.
هل ستحدد هذا أرخص بائع؟
SELECT min(salary), e.* FROM employee e WHERE department = 'sales'
أساسا، هل يمكنني التأكد من أن البيانات التي تم إرجاعها مع وظيفة MIN () ستتطابق مع (أو واحد) سجل مع هذا الحد الأدنى القيمة؟
إذا كانت قاعدة البيانات يهم، أنا أعمل مع MySQL.
المحلول
إذا كنت ترغب في الحصول على موظف "أرخص" في كل قسم سيكون لديك خياران من أعلى رأسي:
SELECT
E.* -- Don't actually use *, list out all of your columns
FROM
Employees E
INNER JOIN
(
SELECT
department,
MIN(salary) AS min_salary
FROM
Employees
GROUP BY
department
) AS SQ ON
SQ.department = E.department AND
SQ.min_salary = E.salary
أو يمكنك استخدام:
SELECT
E.*
FROM
Employees E1
LEFT OUTER JOIN Employees E2 ON
E2.department = E1.department AND
E2.salary < E1.salary
WHERE
E2.employee_id IS NULL -- You can use any NOT NULL column here
تعمل البيان الثاني عن طريق القول بفعالية، أرني جميع الموظفين حيث لا يمكنك العثور على موظف آخر في نفس القسم بأقل راتب.
في كلتا الحالتين، إذا كان لدى اثنان أو أكثر من الموظفين رواتب متساوية، فإن الحد الأدنى الذي ستحصل عليهما (جميعا).
نصائح أخرى
SELECT e.*
FROM employee e
WHERE e.id =
(
SELECT id
FROM employee ei
WHERE ei.department = 'sales'
ORDER BY
e.salary
LIMIT 1
)
للحصول على قيم لكل قسم، استخدم:
SELECT e.*
FROM department d
LEFT JOIN
employee e
ON e.id =
(
SELECT id
FROM employee ei
WHERE ei.department = d.id
ORDER BY
e.salary
LIMIT 1
)
للحصول على القيم فقط لهذه الإدارات التي لديها موظفين، استخدموا:
SELECT e.*
FROM (
SELECT DISTINCT eo.department
FROM employee eo
) d
JOIN
employee e
ON e.id =
(
SELECT id
FROM employee ei
WHERE ei.department = d.department
ORDER BY
e.salary
LIMIT 1
)
بالطبع، وجود مؤشر على (department, salary)
سوف يحسن إلى حد كبير الاستعلامات الثلاثة.
أسرع حلا:
SET @dep := '';
SELECT * FROM (
SELECT * FROM `employee` ORDER BY `department`, `salary`
) AS t WHERE IF ( @dep = t.`department`, FALSE, ( @dep := t.`department` ) OR TRUE );
نهج آخر يمكن أن يستخدم وظائف تحليلية. هنا الاستعلام باستخدام وظائف تحليلية و Row_Num
حدد First_Name، الراتب من (حدد First_name، الراتب، ROW_NUMPER () أكثر (تقسيم بواسطة Department_ID ترتيب الراتب ASC) AS ROW_COUNT من الموظفين) حيث ROW_Count = 1؛