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

นับจำนวนคู่ค่าที่ซ้ำกันในสองคอลัมน์ด้วย GREATEST/LEAST ใน MySQL


สถานการณ์

มีตารางเก็บคู่ค่า (Name1, Name2) ต้องการนับจำนวนครั้งที่คู่ค่านี้ปรากฏ โดยถือว่า (A, B) และ (B, A) เป็นคู่เดียวกัน (Order-independent)

วิธีแก้: ใช้ GREATEST() และ LEAST()

  • GREATEST(a, b) คืนค่าที่มากกว่า
  • LEAST(a, b) คืนค่าที่น้อยกว่า
  • จับคู่ (A, B) และ (B, A) ให้กลายเป็นคู่เดียวกัน (LEAST, GREATEST)

ตัวอย่างการใช้งาน

1. สร้างตาราง

mysql> CREATE TABLE DemoTable (
    -> Name1 VARCHAR(20),
    -> Name2 VARCHAR(20)
    -> );
Query OK, 0 rows affected (0.61 sec)

2. เพิ่มข้อมูล

mysql> INSERT INTO DemoTable VALUES('John', 'Adam');
Query OK, 1 row affected (0.13 sec)
mysql> INSERT INTO DemoTable VALUES('Chris', 'David');
Query OK, 1 row affected (0.17 sec)
mysql> INSERT INTO DemoTable VALUES('Robert', 'Mike');
Query OK, 1 row affected (0.18 sec)
mysql> INSERT INTO DemoTable VALUES('David', 'Chris');  -- สลับลำดับ
Query OK, 1 row affected (0.11 sec)
mysql> INSERT INTO DemoTable VALUES('Mike', 'Robert');  -- สลับลำดับ
Query OK, 1 row affected (0.18 sec)

3. แสดงข้อมูลทั้งหมด

mysql> SELECT * FROM DemoTable;

ผลลัพธ์:

+--------+--------+
| Name1  | Name2  |
+--------+--------+
| John   | Adam   |
| Chris  | David  |
| Robert | Mike   |
| David  | Chris  |
| Mike   | Robert |
+--------+--------+
5 rows in set (0.00 sec)

4. นับจำนวนคู่ (ถือว่า Chris-David = David-Chris)

mysql> SELECT GREATEST(Name1, Name2), LEAST(Name1, Name2), COUNT(*) AS Occurrences
    -> FROM DemoTable
    -> GROUP BY GREATEST(Name1, Name2), LEAST(Name1, Name2);

ผลลัพธ์:

+-----------------------+--------------------+-------------+
| greatest(Name1,Name2) | least(Name1,Name2) | Occurrences |
+-----------------------+--------------------+-------------+
| John                  | Adam               | 1           |
| David                 | Chris              | 2           |
| Robert                | Mike               | 2           |
+-----------------------+--------------------+-------------+
3 rows in set (0.02 sec)

การประยุกต์ใช้

สำหรับตัวเลข (หาคู่ที่ผลรวม/ผลคูณเท่ากัน)

SELECT GREATEST(Val1, Val2), LEAST(Val1, Val2), COUNT(*)
FROM Numbers
GROUP BY GREATEST(Val1, Val2), LEAST(Val1, Val2);

สำหรับวันที่ (หาช่วงเวลาที่ทับซ้อน)

SELECT GREATEST(Start1, Start2), LEAST(End1, End2), COUNT(*)
FROM Events
GROUP BY GREATEST(Start1, Start2), LEAST(End1, End2);

ข้อควรระวัง

  • GREATEST/LEAST คืนค่า NULL หากมี Argument ใดเป็น NULL
  • ใช้ COALESCE() จัดการ NULL ก่อน Group By หากจำเป็น
  • สำหรับ String ใช้ Collation ในการเปรียบเทียบ
  • Performance: ไม่สามารถใช้ Index บน Expression ได้โดยตรง (MySQL 8.0+ ใช้ Functional Index ได้)

กรณีการใช้งานจริง

  • Social Network: นับจำนวน Interaction ระหว่าง User A และ B (ไม่สนทิศทาง)
  • E-commerce: นับคู่สินค้าที่มักซื้อร่วมกัน (Product A + Product B)
  • Logistics: นับเส้นทางไป-กลับ (Origin-Destination vs Destination-Origin)
  • Fraud Detection: หาคู่บัญชีที่โอนเงินไปมาซ้ำกัน