MySQL中將多行查詢結果合並為一行展示SQL語句書寫


寫在前面

  最近開發過程中,遇到一個需求是要將所查詢的多條結果匯總成一條結果展示,由於之前沒有接觸過這方面的業務,所以經過一番折騰之后,解決了需求,這里特此記錄一下,以供后續參考!

1、問題復現

這里以一個例子進行說明:

需求:一個員工每月是否完成了打卡,要求統計員工當月完成和未完成日期,展示結果如下:

測試的數據庫表字段如下:

CREATE TABLE `time_summary` (
  `id` int NOT NULL AUTO_INCREMENT,
  `emp_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '員工號',
  `emp_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '員工姓名',
  `time_date` date DEFAULT NULL COMMENT '填報日期',
  `finish_flag` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '完成標志:0:未完成,1:已完成',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

測試數據如下:

INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (1, '100', '張三', '2020-06-24', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (2, '100', '張三', '2020-06-23', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (3, '100', '張三', '2020-06-22', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (4, '100', '張三', '2020-06-19', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (5, '100', '張三', '2020-06-18', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (6, '100', '張三', '2020-06-17', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (7, '100', '張三', '2020-06-16', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (8, '100', '張三', '2020-06-15', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (9, '100', '張三', '2020-06-12', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (10, '100', '張三', '2020-06-11', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (11, '100', '張三', '2020-06-10', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (12, '100', '張三', '2020-06-09', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (13, '100', '張三', '2020-06-08', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (14, '100', '張三', '2020-06-05', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (15, '100', '張三', '2020-06-04', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (16, '100', '張三', '2020-06-03', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (17, '100', '張三', '2020-06-02', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (18, '100', '張三', '2020-06-01', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (19, '101', '李四', '2020-06-24', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (20, '101', '李四', '2020-06-23', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (21, '101', '李四', '2020-06-22', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (22, '101', '李四', '2020-06-19', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (23, '101', '李四', '2020-06-18', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (24, '101', '李四', '2020-06-17', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (25, '101', '李四', '2020-06-16', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (26, '101', '李四', '2020-06-15', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (27, '101', '李四', '2020-06-12', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (28, '101', '李四', '2020-06-11', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (29, '101', '李四', '2020-06-10', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (30, '101', '李四', '2020-06-09', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (31, '101', '李四', '2020-06-08', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (32, '101', '李四', '2020-06-05', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (33, '101', '李四', '2020-06-04', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (34, '101', '李四', '2020-06-03', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (35, '101', '李四', '2020-06-02', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (36, '101', '李四', '2020-06-01', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (37, '102', '王五', '2020-06-24', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (38, '102', '王五', '2020-06-23', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (39, '102', '王五', '2020-06-22', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (40, '102', '王五', '2020-06-19', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (41, '102', '王五', '2020-06-18', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (42, '102', '王五', '2020-06-17', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (43, '102', '王五', '2020-06-16', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (44, '102', '王五', '2020-06-15', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (45, '102', '王五', '2020-06-12', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (46, '102', '王五', '2020-06-11', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (47, '102', '王五', '2020-06-10', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (48, '102', '王五', '2020-06-09', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (49, '102', '王五', '2020-06-08', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (50, '102', '王五', '2020-06-05', '1');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (51, '102', '王五', '2020-06-04', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (52, '102', '王五', '2020-06-03', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (53, '102', '王五', '2020-06-02', '0');
INSERT INTO `time_summary`(`id`, `emp_id`, `emp_name`, `time_date`, `finish_flag`) VALUES (54, '102', '王五', '2020-06-01', '0');
View Code

這種情況下,我們一般可以將所有的情況查詢出來(這里以6月份數據為例),查詢SQL如下:

SELECT t.emp_id,t.emp_name,t.time_date,t.finish_flag from time_summary t 
where t.time_date >= '2020-06-01' and time_date <= '2020-06-30'

這樣查詢的結果如下:

 這種顯然不滿足要求,針對這種情況,要怎么做呢?

 2、問題解決

這時候需要使用 GROUP_CONCAT() 函數解決此問題。

說明:

1.GROUP_CONCAT() 中的值為你要合並的數據的字段名;

 SEPARATOR 函數是用來分隔這些要合並的數據的,默認以 逗號 分隔;

 ' '中是你要用哪個符號來分隔;

2.必須要用GROUP BY 語句來進行分組管理,不然所有的數據都會被合並成一條記錄

則此處對應的SQL語句如下,僅供參考!

SELECT
    su.emp_id,
    su.emp_name,
    a.notFinished,
    b.finished 
FROM
    (
    SELECT
        t.emp_id,
        t.emp_name 
    FROM
        time_summary t 
    WHERE
        t.time_date >= '2020-06-01' 
        AND t.time_date <= '2020-06-30' 
    GROUP BY
        t.emp_id,
        t.emp_name 
    ) su
    LEFT JOIN (
    SELECT
        t.emp_id,
        t.emp_name,
        GROUP_CONCAT( SUBSTRING( t.time_date, 9, 2 ) SEPARATOR ',' ) AS notFinished 
    FROM
        time_summary t 
    WHERE
        t.time_date >= '2020-06-01' 
        AND t.time_date <= '2020-06-30' 
        AND t.finish_flag = '0' 
    GROUP BY
        t.emp_id,
        t.emp_name 
    ) a ON su.emp_id = a.emp_id
    LEFT JOIN (
    SELECT
        t.emp_id,
        t.emp_name,
        GROUP_CONCAT( SUBSTRING( t.time_date, 9, 2 ) SEPARATOR ',' ) AS finished 
    FROM
        time_summary t 
    WHERE
        t.time_date >= '2020-06-01' 
        AND t.time_date <= '2020-06-30' 
        AND t.finish_flag = '1' 
    GROUP BY
        t.emp_id,
        t.emp_name 
    ) b ON su.emp_id = b.emp_id

3、內容擴展

在MySQL中字符串拼接常用的方法整理:
 1、CONCAT()
 2、CONCAT_WS()
 3、GROUP_CONCAT()

3.1 CONCAT()

語法:CONCAT(str1,str2,...)
說明:作為最常用的字符串拼接方法,但是CONCAT函數在遇到拼接中的字符串出現 NULL 的情況,會返回 NULL

示例:

3.2 CONCAT_WS()

此種連接字符串的方法,從名字上就能看出:從concat with separator,使用分隔符連接字符串。

語法:CONCAT_WS(separator,str1,str2,…)
使用說明:第一個參數separator是用來分隔其它參數的分隔符。分隔符的位置放在要連接的兩個字符串之間。分隔符可以是一個字符串,也可以是其它參數
對比說明:concat_ws與concat相比優點:
         1、可以使用分隔符連接字符串
         2、若連接的字符串出現 NULL 值,concat_ws會忽略 NULL 值,
            返回其他連接字符串

示例1:

示例2:

 

3.3 GROUP_CONCAT()

此種連接方法,主要是將某一字段的值連接成一行進行顯示,具體可以參看上面的問題實例。

語法 :group_concat( [DISTINCT] 連接的字段 [Order BY 排序字段 ASC/DESC] [Separator ‘分隔符’] )
說明:可以連接多個字段,也可以對連接字段進行排序,默認以 逗號 分隔字段


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM