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

MySQL: แสดงชื่อคอลัมน์ที่ไม่ซ้ำ (Distinct) ด้วย GROUP BY

สร้างตารางและข้อมูลตัวอย่าง

mysql> create table DemoTable1996 ( ShippingDate datetime, CustomerName varchar(20) );
mysql> insert into DemoTable1996 values('2019-12-21 10:45:00','Chris');
mysql> insert into DemoTable1996 values('2019-12-21 12:10:00','David');
mysql> insert into DemoTable1996 values('2019-12-20 12:10:00','Bob');

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

+---------------------+--------------+
| ShippingDate        | CustomerName |
+---------------------+--------------+
| 2019-12-21 10:45:00 | Chris        |
| 2019-12-21 12:10:00 | David        |
| 2019-12-20 12:10:00 | Bob          |
+---------------------+--------------+

Query ใช้ GROUP BY DATE(ShippingDate)

mysql> select * from DemoTable1996 group by date(ShippingDate);

ผลลัพธ์

+---------------------+--------------+
| ShippingDate        | CustomerName |
+---------------------+--------------+
| 2019-12-21 10:45:00 | Chris        |
| 2019-12-20 12:10:00 | Bob          |
+---------------------+--------------+

อธิบาย

  • GROUP BY DATE(ShippingDate) จับกลุ่มตามวันที่ (ตัดเวลาออก)
  • วันที่ 2019-12-21 มี 2 แถว (Chris, David) → เลือกแถวแรกที่เจอ (Chris)
  • วันที่ 2019-12-20 มี 1 แถว (Bob) → เลือก Bob

⚠️ ข้อควรระวัง: Non-Aggregated Columns

Query นี้ใช้ SELECT * พร้อม GROUP BY บนคอลัมน์ที่ไม่ได้อยู่ใน GROUP BY และไม่ได้อยู่ใน Aggregate Function

  • MySQL ก่อน 5.7.5: อนุญาต ให้ผลลัพธ์ไม่แน่นอน (Indeterminate)
  • MySQL 5.7.5+ (Default ONLY_FULL_GROUP_BY): Error หากไม่ได้อยู่ใน GROUP BY หรือ Aggregate
  • MySQL 8.0+: บังคับ ONLY_FULL_GROUP_BY ตลอด

วิธีเขียนที่ถูกต้องและปลอดภัย (Standard SQL)

-- 1. ใช้ Aggregate Function
SELECT DATE(ShippingDate) AS ShipDate, MIN(CustomerName) AS FirstCustomer
FROM DemoTable1996 GROUP BY DATE(ShippingDate);

-- 2. ใช้ ANY_VALUE() (MySQL 5.7.5+) ระบุว่า "รับค่าไหนก็ได้"
SELECT DATE(ShippingDate) AS ShipDate, ANY_VALUE(CustomerName) AS CustomerName
FROM DemoTable1996 GROUP BY DATE(ShippingDate);

-- 3. Subquery หา ID แล้ว JOIN กลับ
SELECT t1.* FROM DemoTable1996 t1
JOIN (
    SELECT MIN(Id) AS Id FROM DemoTable1996 GROUP BY DATE(ShippingDate)
) t2 ON t1.Id = t2.Id;

สรุป

ตัวอย่างเดิมทำงานได้ใน MySQL เก่าหรือที่ปิด ONLY_FULL_GROUP_BY แต่ ไม่แนะนำ สำหรับ Production ควรเขียนแบบ Standard SQL ด้านบน