# MySQL怎么實現多行轉一行
## 引言
在數據庫操作中,我們經常會遇到需要將多行數據合并成一行的場景。例如將某個分組下的多條記錄合并為一條記錄展示,或將多行文本拼接成單個字符串。MySQL提供了多種實現方式,本文將詳細介紹5種常用方法及其適用場景。
## 一、GROUP_CONCAT函數
### 1.1 基本語法
```sql
GROUP_CONCAT([DISTINCT] column_name
[ORDER BY sort_column ASC/DESC]
[SEPARATOR '分隔符'])
-- 基礎用法
SELECT department_id,
GROUP_CONCAT(employee_name) AS employees
FROM employees
GROUP BY department_id;
-- 帶分隔符和排序
SELECT product_id,
GROUP_CONCAT(DISTINCT tag_name ORDER BY tag_id SEPARATOR '|')
FROM product_tags
GROUP BY product_id;
group_concat_max_len
參數調整)SELECT
user_id,
(SELECT GROUP_CONCAT(order_id)
FROM orders
WHERE user_id = u.user_id) AS order_list
FROM users u;
SELECT
department,
CONCAT_WS(',',
MAX(CASE WHEN seq = 1 THEN name END),
MAX(CASE WHEN seq = 2 THEN name END)
) AS members
FROM (
SELECT
department,
name,
@rn := IF(@dept = department, @rn + 1, 1) AS seq,
@dept := department
FROM employees, (SELECT @rn := 0, @dept := '') r
ORDER BY department, name
) t
GROUP BY department;
DELIMITER //
CREATE PROCEDURE concat_employee_names(IN dept_id INT)
BEGIN
DECLARE result TEXT DEFAULT '';
DECLARE done INT DEFAULT FALSE;
DECLARE emp_name VARCHAR(100);
DECLARE cur CURSOR FOR
SELECT name FROM employees WHERE department_id = dept_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO emp_name;
IF done THEN
LEAVE read_loop;
END IF;
SET result = CONCAT(result, emp_name, ',');
END LOOP;
CLOSE cur;
SELECT dept_id AS department_id,
LEFT(result, LENGTH(result)-1) AS employee_list;
END //
DELIMITER ;
SELECT
department_id,
JSON_ARRAYAGG(employee_name) AS json_employee_array
FROM employees
GROUP BY department_id;
SELECT
project_id,
JSON_OBJECTAGG(employee_id, hours_worked) AS team_hours
FROM project_assignments
GROUP BY project_id;
SELECT
IFNULL(department, 'ALL') AS department,
GROUP_CONCAT(DISTINCT position) AS positions,
COUNT(*) AS employee_count
FROM employees
GROUP BY department WITH ROLLUP;
方法 | 適用版本 | 性能表現 | 功能復雜度 |
---|---|---|---|
GROUP_CONCAT | 4.1+ | ★★★★☆ | ★★☆☆☆ |
子查詢拼接 | 所有版本 | ★★☆☆☆ | ★★★☆☆ |
存儲過程 | 所有版本 | ★★★☆☆ | ★★★★☆ |
JSON函數 | 5.7+ | ★★★★☆ | ★★★☆☆ |
WITH ROLLUP | 4.1+ | ★★★☆☆ | ★★★☆☆ |
SELECT
product_id,
GROUP_CONCAT(
CONCAT(attr_name, ':', attr_value)
SEPARATOR '; '
) AS product_attributes
FROM product_specs
GROUP BY product_id;
SELECT
u.user_id,
u.username,
GROUP_CONCAT(r.role_name ORDER BY r.role_level DESC) AS roles
FROM users u
JOIN user_roles ur ON u.user_id = ur.user_id
JOIN roles r ON ur.role_id = r.role_id
GROUP BY u.user_id, u.username;
-- 臨時設置更大的長度限制
SET SESSION group_concat_max_len = 1000000;
SELECT GROUP_CONCAT(...);
-- 使用REPLACE處理分隔符沖突
SELECT
GROUP_CONCAT(REPLACE(text_field, ',', ',') SEPARATOR ',')
FROM table;
MySQL實現多行轉一行主要有以下幾種方式: 1. 優先推薦:GROUP_CONCAT(簡單高效) 2. 復雜邏輯:存儲過程(靈活可控) 3. 現代方案:JSON函數(結構化輸出) 4. 兼容方案:子查詢拼接(低版本兼容)
根據實際業務需求選擇合適的方法,同時注意處理大數據量時的性能問題。對于超大數據集,建議在應用層進行處理。 “`
注:本文實際約1500字,完整版可根據需要擴展具體示例和性能測試數據。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。