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

Select แถวที่ Column ต้องตรงหลายค่าใน MySQL ด้วย GROUP BY HAVING

การเตรียมข้อมูล

mysql> CREATE TABLE DemoTable1885 (
    FirstName VARCHAR(20),
    Subject VARCHAR(50)
);

mysql> INSERT INTO DemoTable1885 VALUES
    ('John', 'MySQL'), ('John', 'MongoDB'),
    ('Carol', 'MySQL'), ('David', 'Java');

ข้อมูลในตาราง

+-----------+---------+
| FirstName | Subject |
+-----------+---------+
| John      | MySQL   |
| John      | MongoDB |
| Carol     | MySQL   |
| David     | Java    |
+-----------+---------+

หา FirstName ที่มีทั้ง MySQL และ MongoDB

mysql> SELECT FirstName FROM DemoTable1885
    WHERE Subject IN ('MySQL', 'MongoDB')
    GROUP BY FirstName
    HAVING COUNT(*) = 2;

ผลลัพธ์:

+-----------+
| FirstName |
+-----------+
| John      |
+-----------+

หลักการทำงาน

  1. WHERE Subject IN (...) กรองเฉพาะ Subject ที่สนใจ
  2. GROUP BY FirstName จับกลุ่มตามคน
  3. HAVING COUNT(*) = 2 ต้องมี 2 แถว (ตรงกับจำนวนใน IN)

ขยาย: 3 Subject ขึ้นไป

SELECT FirstName FROM DemoTable1885
WHERE Subject IN ('MySQL', 'MongoDB', 'PostgreSQL')
GROUP BY FirstName
HAVING COUNT(DISTINCT Subject) = 3;  -- ใช้ DISTINCT ป้องกัน Duplicate

วิธีอื่น: INTERSECT Logic (MySQL ไม่มี INTERSECT)

-- ใช้ INNER JOIN หลายครั้ง
SELECT DISTINCT t1.FirstName
FROM DemoTable1885 t1
JOIN DemoTable1885 t2 ON t1.FirstName = t2.FirstName AND t2.Subject = 'MongoDB'
WHERE t1.Subject = 'MySQL';

-- ใช้ EXISTS
SELECT DISTINCT FirstName FROM DemoTable1885 t1
WHERE Subject = 'MySQL'
AND EXISTS (SELECT 1 FROM DemoTable1885 t2 WHERE t2.FirstName = t1.FirstName AND t2.Subject = 'MongoDB');

Relational Division

ปัญหานี้เรียกว่า Relational Division - หา Entity ที่มี Relationship ครบทุกค่าที่กำหนด