Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

Query หาแถวเงินเดือนสูงสุดและต่ำสุดใน MySQL ด้วย Subquery และ UNION ALL

หาแถวที่มี Salary Min และ Max พร้อมกัน

ใช้ Subquery หา MIN/MAX แล้ว UNION ALL รวมผลลัพธ์ (UNION จะ DISTINCT อาจลบแถวซ้ำถ้า Min=Max)

สร้างตารางและข้อมูล

mysql> CREATE TABLE DemoTable (
    -> EmployeeName VARCHAR(20),
    -> EmployeeSalary INT
    -> );
Query OK, 0 rows affected (0.70 sec)

mysql> INSERT INTO DemoTable VALUES
    -> ('Bob', 8800), ('Chris', 9800), ('David', 7600), ('Sam', 9600);
Query OK, 4 rows affected

ข้อมูลทั้งหมด

+--------------+----------------+
| EmployeeName | EmployeeSalary |
+--------------+----------------+
| Bob          |           8800 |
| Chris        |           9800 |
| David        |            7600 |
| Sam          |           9600 |
+--------------+----------------+

คำสั่ง: Subquery + UNION ALL

mysql> SELECT * FROM DemoTable
    -> WHERE EmployeeSalary IN (
    ->     SELECT MAX(EmployeeSalary) FROM DemoTable
    ->     UNION ALL
    ->     SELECT MIN(EmployeeSalary) FROM DemoTable
    -> );

ผลลัพธ์

+--------------+----------------+
| EmployeeName | EmployeeSalary |
+--------------+----------------+
| Chris        |           9800 |  -- MAX
| David        |           7600 |  -- MIN
+--------------+----------------+

คำอธิบาย

  • SELECT MAX(EmployeeSalary) FROM DemoTable → 9800
  • SELECT MIN(EmployeeSalary) FROM DemoTable → 7600
  • UNION ALL → รวมเป็นชุด {9800, 7600} (เก็บ Duplicate ไว้)
  • WHERE EmployeeSalary IN (...) → กรองแถวที่ Salary อยู่ในชุดนี้

วิธีอื่น: ใช้ Window Functions (MySQL 8.0+)

SELECT EmployeeName, EmployeeSalary
FROM (
    SELECT *,
        MAX(EmployeeSalary) OVER () AS max_sal,
        MIN(EmployeeSalary) OVER () AS min_sal
    FROM DemoTable
) t
WHERE EmployeeSalary = max_sal OR EmployeeSalary = min_sal;

วิธีอื่น: ใช้ JOIN

SELECT t.EmployeeName, t.EmployeeSalary
FROM DemoTable t
JOIN (
    SELECT MAX(EmployeeSalary) AS max_sal, MIN(EmployeeSalary) AS min_sal
    FROM DemoTable
) agg ON t.EmployeeSalary = agg.max_sal OR t.EmployeeSalary = agg.min_sal;

⚠️ ข้อควรระวัง: UNION vs UNION ALL

  • UNION = DISTINCT (ลบแถวซ้ำ) → หาก Max = Min จะได้ 1 แถว
  • UNION ALL = เก็บทุกแถว → หาก Max = Min จะได้ 2 แถว (ซ้ำกัน)
  • ที่นี่ใช้ UNION ALL เพื่อความเร็วและความถูกต้อง

กรณีมีหลายคน Salary เท่ากัน Max/Min

Query เดิมจะคืน ทุกคน ที่มี Salary = Max หรือ Min (ถูกต้อง)