Mysql逗號(hào)拼接字符串的關(guān)聯(lián)查詢以及統(tǒng)計(jì)問題
背景:
數(shù)據(jù)庫中逗號(hào)拼接的字符串,想展示其完整拼接名稱或者按其值統(tǒng)計(jì)處理,怎么做?
FIND_IN_SET函數(shù)和GROUP_CONCAT函數(shù)你會(huì)用嗎?
一、查詢問題
eg兩張表 t_conclusion_detail(拜訪信息表) 和 t_conclusion_info(拜訪結(jié)論表)
t_conclusion_detail:
| id | userName | conclusionIds |
|---|---|---|
| 781918060586991616 | 夢(mèng)琪 | 1,3 |
| 781986564770103296 | 西施 | 3 |
| 781989822074978304 | 火舞 | 2,3,4 |
t_conclusion_info:
| conclusionId | conclusionName |
|---|---|
| 1 | 已成交 |
| 2 | 暫無興趣 |
| 3 | 需要跟進(jìn) |
| 4 | 溝通順利 |
想要的效果:
| id | userName | conclusionIds | conclusionNameStr |
|---|---|---|---|
| 781918060586991616 | 夢(mèng)琪 | 1,3 | 已成交,需要跟進(jìn) |
| 781986564770103296 | 西施 | 3 | 需要跟進(jìn) |
| 781989822074978304 | 火舞 | 2,3,4 | 暫無興趣,需要跟進(jìn),溝通順利 |
思考??:
一般這種情況兩種方案:要么代碼層面處理,要么數(shù)據(jù)庫層面處理
1、方案一( 代碼層面):先查拜訪信息表,將數(shù)據(jù)返回到服務(wù)器,在代碼里進(jìn)行切割,然后再去拜訪結(jié)論表里面去查詢對(duì)應(yīng)的名稱,返回到程序進(jìn)行處理拼接。造成頻繁訪問數(shù)據(jù)庫,或需要批量查回再匹配處理,這樣做雖然很簡單也很好理解但是效率太低。
2、方案二(數(shù)據(jù)庫):以mysql為例,使用FIND_IN_SET函數(shù)和GROUP_CONCAT函數(shù)進(jìn)行查詢,但是數(shù)據(jù)量特別大時(shí)可能不友好,利用不上索引等
SELECT s.id,s.user_name userName,s.conclusion_ids conclusionIds, (SELECT GROUP_CONCAT(user_name) FROM t_conclusion_info tr WHERE FIND_IN_SET(tr.conclusion_id,(SELECT conclusion_ids FROM t_conclusion_detail WHERE id=s.id))) AS conclusionNameStr FROM t_conclusion_detail s
tip:如果數(shù)據(jù)量特別大建議還是設(shè)計(jì)時(shí)不要逗號(hào)拼接設(shè)計(jì),改成多表聯(lián)查,或者使用代碼層面處理
二、統(tǒng)計(jì)問題
還是上述兩張表,想要的效果是每個(gè)結(jié)論出現(xiàn)頻次的統(tǒng)計(jì),即統(tǒng)計(jì)逗號(hào)拼接的字符串中內(nèi)容
偽代碼,具體根據(jù)情況拼接業(yè)務(wù)sql:
SELECT
sum(case when find_in_set('1',conclusion_ids)>0 then 1 else 0 end) one,
sum(case when find_in_set('2',conclusion_ids) >0 then 1 else 0 end) two,
sum(case when find_in_set('3',conclusion_ids) >0 then 1 else 0 end) three,
sum(case when find_in_set('4',conclusion_ids) >0 then 1 else 0 end) four
from t_conclusion_detail
結(jié)果:
| one | two | three | four |
|---|---|---|---|
| 1 | 1 | 3 | 1 |
三、效率問題
思考??: 模擬插入20萬數(shù)據(jù),查看find_in_set效率問題:
CREATE TABLE `t_conclusion_detail` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵', `user_name` varchar(32) COMMENT '姓名', `conclusion_ids` varchar(32) COMMENT '拜訪結(jié)論(多個(gè)結(jié)論逗號(hào)分隔)' PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 COMMENT='拜訪記錄表';
DROP PROCEDURE IF EXISTS `t_conclusion_detail_memory`
DELIMITER //
CREATE PROCEDURE `t_conclusion_detail_memory`(IN n INT)
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE id INT DEFAULT 1;
DECLARE num1 INT DEFAULT 1;
DECLARE num2 INT DEFAULT 1;
DECLARE num3 INT DEFAULT 1;
WHILE i < n DO
SET id = i;
SET num1 = FLOOR(0 + RAND()*6);
SET num2 = FLOOR(0 + RAND()*6);
SET num3 = FLOOR(0 + RAND()*6);
INSERT INTO `t_conclusion_detail` VALUES (id, 'test', concat(num1,',',num2,',',num3), );
SET i = i + 1;
END WHILE;
END //
DELIMITER ; -- 改回默認(rèn)的 MySQL delimiter:';'
CALL t_conclusion_detail_memory(200000); 經(jīng)實(shí)驗(yàn),20w數(shù)據(jù)時(shí)相關(guān)查詢最慢2s左右,可接受范圍。
總結(jié)
到此這篇關(guān)于Mysql逗號(hào)拼接字符串的關(guān)聯(lián)查詢以及統(tǒng)計(jì)問題的文章就介紹到這了,更多相關(guān)Mysql逗號(hào)拼接字符串查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL 原理與優(yōu)化之Update 優(yōu)化
這篇文章主要介紹了MySQL 原理與優(yōu)化之Update 優(yōu)化,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下,希望對(duì)你的學(xué)習(xí)有所幫助2022-08-08
MySQL多表關(guān)聯(lián)查詢方式及實(shí)際應(yīng)用
MySQL語句學(xué)習(xí)的難點(diǎn)和重點(diǎn)就在于多表查詢,同時(shí)MySQL也有諸多方法供大家選擇,不論是多表聯(lián)查(聯(lián)結(jié)表、左連接、右連接……),這篇文章主要給大家介紹了關(guān)于MySQL多表關(guān)聯(lián)查詢方式及實(shí)際應(yīng)用的相關(guān)資料,需要的朋友可以參考下2024-07-07
MySQL中查詢某一天, 某一月, 某一年的數(shù)據(jù)代碼詳解
本文通過實(shí)例代碼給大家介紹了MySQL中, 如何查詢某一天, 某一月, 某一年的數(shù)據(jù) ,需要的朋友可以參考下2019-06-06
詳解MySQL插入和查詢數(shù)據(jù)的相關(guān)命令及語句使用
這篇文章主要介紹了MySQL插入和查詢數(shù)據(jù)的相關(guān)命令及語句使用,包括相關(guān)的PHP腳本操作方法講解也很詳細(xì),需要的朋友可以參考下2015-11-11

