前言

我們在做專案寫sql語句的時候,是否會遇到這樣的場景,就是需要把查詢出來的多列,按照字串分割合併成一列顯示,或者把存在資料庫裡面用逗號分隔的一列,查詢分成多列呢,常見場景有,文章標籤,需要吧查詢多個標籤合併成一列,等,需要怎麼去實現呢,這就涉及到MySQL的字串操作

group_concat

場景再現 我想把查詢多列資料合併成一列顯示用逗號分隔就需要用到group_concat這個函式

下面sql語句

select r.ROLE_NAME
from t_user u
right join t_user_role ur on ur.USER_ID = u.USER_ID,
t_role r
where r.ROLE_ID = ur.ROLE_ID
and u.USER_ID = 7

ID為7的使用者有兩個角色,但是我現在想把它顯示成一列,就需要用到字串函式group_concat 如下sql

select group_concat(r.ROLE_NAME)
from t_user u
right join t_user_role ur on ur.USER_ID = u.USER_ID,
t_role r
where r.ROLE_ID = ur.ROLE_ID
and u.USER_ID = 7;

實現了我需要的功能

當然group_concat函式預設使用逗號,進行連線,我們也可以自己指定分隔連擊符如group_concat(name separator ';')

select group_concat(r.ROLE_NAME separator ';')
from t_user u
right join t_user_role ur on ur.USER_ID = u.USER_ID,
t_role r
where r.ROLE_ID = ur.ROLE_ID
and u.USER_ID = 7;

當然實際應用不單單這麼簡單,需要結合子查詢使用,

如下sql 查詢使用者詳細資訊,就包括使用者角色資訊部門資訊

select tu.*,
d.DEPT_NAME,
(select group_concat(r.ROLE_NAME)
from t_user u
left join t_user_role ur on ur.USER_ID = u.USER_ID,
t_role r
where r.ROLE_ID = ur.ROLE_ID
and u.USER_ID = tu.USER_ID) as roles
from t_user tu
left join
t_dept d
on tu.DEPT_ID = d.DEPT_ID
where tu.USER_ID=7;

substring_index(str,delim,count)

場景在現某些業務表出於歷史原因或效能原因,都使用了違反第一正規化的設計模式。即同一個列中儲存了多個屬性值。如下表中的 theme 所示:

這種情況下,可以考慮將該列根據分隔符進行分割,形成多個列就需要使用到substring_index函式

SUBSTRING_INDEX(str,delim,count)
-- str: 被分割的字串; delim: 分隔符; count: 分割符出現的次數

對於字串 “1,2,3” ,設定delim為 “,”,count為1,就會返回 “1”;其它引數不變,count為2,就會返回 “1,2”;其它引數不變,count為-1,就會返回 “3”。

如下sql

select USERNAME,
(select substring_index(tu.THEME, ',', 1) from t_user tu where tu.USER_ID = 1) theme1,
(select substring_index(tu.THEME, ',', 2) from t_user tu where tu.USER_ID = 1) theme2,
(select substring_index(tu.THEME, ',', -1) from t_user tu where tu.USER_ID = 1) theme3
from t_user
where USER_ID = 1;

顯然不符合我們所需要的,我們可以在巢狀sql自查詢實現如下

select USERNAME,
(select substring_index(tu.THEME, ',', 1) from t_user tu where tu.USER_ID = 1) theme1,
(select substring_index((select substring_index(tu.THEME, ',', 2) from t_user tu where tu.USER_ID = 1),',',-1) theme2),
(select substring_index(tu.THEME, ',', -1) from t_user tu where tu.USER_ID = 1) theme3
from t_user
where USER_ID = 1;

當然這個計算應該是動態的可以參考參考實現