การสร้างหมายเลขลำดับ (Numbering) ภายใน GROUP_CONCAT ตามกลุ่ม
บทความนี้แสดงวิธีใช้ตัวแปรผู้ใช้ (user-defined variables) ร่วมกับ GROUP_CONCAT เพื่อสร้างหมายเลขลำดับอัตโนมัติสำหรับแต่ละกลุ่ม (group) ใน MySQL
สร้างตารางและเพิ่มข้อมูล
mysql> create table DemoTable1627 (
-> FirstName varchar(20),
-> LastName varchar(20)
-> );
Query OK, 0 rows affected (0.59 sec)
mysql> insert into DemoTable1627 values('John','Smith');
mysql> insert into DemoTable1627 values('John','Doe');
mysql> insert into DemoTable1627 values('Adam','Smith');
mysql> insert into DemoTable1627 values('Carol','Taylor');
ข้อมูลต้นฉบับ
+-----------+----------+ | FirstName | LastName | +-----------+----------+ | John | Smith | | John | Doe | | Adam | Smith | | Carol | Taylor | +-----------+----------+
คำสั่ง SQL สำหรับเพิ่มหมายเลขลำดับใน GROUP_CONCAT
mysql> select LastName,
-> group_concat(
-> concat(@j := if (@p = LastName, @j + 1, if(@p := LastName,1,1)), '.', FirstName)
-> separator ', ') FirstName
-> from DemoTable1627
-> group by LastName;
ผลลัพธ์
+----------+----------------+ | LastName | FirstName | +----------+----------------+ | Doe | 1.John | | Smith | 1.John, 2.Adam | | Taylor | 1.Carol | +----------+----------------+
อธิบายตรรกะสำคัญ
@p— เก็บค่าLastNameของแถวก่อนหน้า@j— ตัวนับลำดับภายในกลุ่มif (@p = LastName, @j + 1, ...)— หากLastNameเดียวกับแถวก่อน ให้เพิ่มลำดับ (+1)if(@p := LastName,1,1)— หากเปลี่ยนกลุ่ม ให้กำหนด@pใหม่และรีเซ็ต@jเป็น 1concat(..., '.', FirstName)— รวมหมายเลขจุดกับชื่อ
ข้อควรระวัง: การใช้ตัวแปรผู้ใช้ในลักษณะนี้อาจให้ผลลัพธ์ที่ไม่คาดคิดใน MySQL 8.0+ เนื่องจากลำดับการประเมินค่า (evaluation order) ไม่ได้รับการรับประกัน ควรพิจารณาใช้ ROW_NUMBER() OVER (PARTITION BY LastName ORDER BY FirstName) ใน MySQL 8.0 ขึ้นไปแทน ซึ่งเป็นมาตรฐานและน่าเชื่อถือกว่า