MySQL中concat()、concat_ws()卫枝、group_concat()函數(shù)的使用技巧與心得總結(jié)

作者:極客小俊 一個(gè)專注于web技術(shù)的80后
我不用拼過聰明人煎饼,我只需要拼過那些懶人 我就一定會(huì)超越大部分人!
@極客小俊,簡書官方首發(fā)原創(chuàng)文章
企業(yè)博客: ?? GeekerJun ??
B站干貨 : ?? Bilibili.com ??

fun.jpg

前言

GROUP_CONCAT()函數(shù)在MySQL到底起什么作用呢 校赤?

有些小伙伴還覺得它很神秘其實(shí)不然吆玖,今天就來講講這個(gè)函數(shù)的實(shí)際操作以及相關(guān)案例、

我將從concat()函數(shù) --- concat_ws()函數(shù)----到最后的group_concat()函數(shù)逐一講解! 讓小伙伴摸清楚其使用方法 !

首先我們來建立一個(gè)測(cè)試的表和數(shù)據(jù)马篮,代碼如下

CREATE TABLE `per` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `pname` varchar(50) DEFAULT NULL,
  `page` int(11) DEFAULT NULL,
  `psex` varchar(50) DEFAULT NULL,
  `paddr` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4;


INSERT INTO `per` VALUES ('1', '王小華', '30', '男', '北京');
INSERT INTO `per` VALUES ('2', '張文軍', '24', '男', '上海');
INSERT INTO `per` VALUES ('3', '羅敏', '19', '女', '重慶');
INSERT INTO `per` VALUES ('4', '張建新', '32', '男', '重慶');
INSERT INTO `per` VALUES ('5', '劉婷', '26', '女', '成都');
INSERT INTO `per` VALUES ('6', '劉小亞', '22', '女', '重慶');
INSERT INTO `per` VALUES ('7', '王建軍', '22', '男', '貴州');
INSERT INTO `per` VALUES ('8', '謝濤', '28', '男', '海南');
INSERT INTO `per` VALUES ('9', '張良', '26', '男', '上海');
INSERT INTO `per` VALUES ('10', '黎記', '17', '男', '貴陽');
INSERT INTO `per` VALUES ('11', '趙小麗', '26', '女', '上海');
INSERT INTO `per` VALUES ('12', '張三', null, '女', '北京');
concat()函數(shù)

首先我們先學(xué)一個(gè)函數(shù)叫concat()函數(shù), 這個(gè)函數(shù)非常簡單

功能:就是將多個(gè)字符串連接成一個(gè)字符串

語法:concat(字符串1, 字符串2,...) 字符串參數(shù)用逗號(hào)隔開!

返回值: 結(jié)果為連接參數(shù)產(chǎn)生的字符串沾乘,如果有任何一個(gè)參數(shù)為null,則返回值為null浑测。

案例1

select concat('重慶','北京','上海');

效果如下圖: 是不是覺得很簡單 很直觀呢!

1.png

案例2

這有一張表

+----+-----------+------+------+--------+
| id | pname     | page | psex | paddr  |
+----+-----------+------+------+--------+
|  1 | 王小華    |   30 | 男   | 北京   |
|  2 | 張文軍    |   24 | 男   | 上海   |
|  3 | 羅敏      |   19 | 女   | 重慶   |
|  4 | 張建新    |   32 | 男   | 重慶   |
|  5 | 劉婷      |   26 | 女   | 成都   |
|  6 | 劉小亞    |   22 | 女   | 重慶   |
|  7 | 王建軍    |   22 | 男   | 貴州   |
|  8 | 謝濤      |   28 | 男   | 海南   |
|  9 | 張良      |   26 | 男   | 上海   |
| 10 | 黎記      |   17 | 男   | 貴陽   |
| 11 | 趙小麗    |   26 | 女   | 上海   |
| 12 | 張三      | NULL | 女   | 北京   |
+----+-----------+------+------+--------+

#-- 執(zhí)行如下語句
select concat(pname,page,psex) from per;

#--結(jié)果
+-------------------------+
| concat(pname,page,psex) |
+-------------------------+
| 王小華30男              |
| 張文軍24男              |
| 羅敏19女                |
| 張建新32男              |
| 劉婷26女                |
| 劉小亞22女              |
| 王建軍22男              |
| 謝濤28男                |
| 張良26男                |
| 黎記17男                |
| 趙小麗26女              |
| NULL                    |
+-------------------------+

#--為什么會(huì)有一條是NULL呢?  
#--那是因?yàn)榈?2條數(shù)據(jù)中的page字段為空翅阵,根據(jù)有一個(gè)字段為空結(jié)果就為NULL的理論推導(dǎo)出 查詢出的最后一條記錄為NULL!


但是大家一定會(huì)發(fā)現(xiàn)雖然連在一起顯示了 但是彼此沒有分隔符啊 看起來好難受 對(duì)不對(duì)? 所以接下來我們就來講講衍生出來的 concat_ws()函數(shù)

concat_ws()函數(shù)

功能:concat_ws()函數(shù) 和 concat()函數(shù)一樣,也是將多個(gè)字符串連接成一個(gè)字符串掷匠,但是可以指定分隔符!

語法:concat_ws(separator, str1, str2, ...) 第一個(gè)參數(shù)指定分隔符, 后面依舊是字符串

separator就是分隔符字符!

需要注意的是分隔符不能為null滥崩,如果為null,則返回結(jié)果為null槐雾。

案例代碼:

select concat_ws(',',pname,page,psex) from per;  
#--以逗號(hào)分割 結(jié)果如下
+--------------------------------+
| concat_ws(',',pname,page,psex) |
+--------------------------------+
| 王小華,30,男                   |
| 張文軍,24,男                   |
| 羅敏,19,女                     |
| 張建新,32,男                   |
| 劉婷,26,女                     |
| 劉小亞,22,女                   |
| 王建軍,22,男                   |
| 謝濤,28,男                     |
| 張良,26,男                     |
| 黎記,17,男                     |
| 趙小麗,26,女                   |
| 張三,女                        |
+--------------------------------+

#--把分隔符指定為null夭委,結(jié)果全部變成了null

select concat_ws(null,pname,page,psex) from per;   #--錯(cuò)誤的
+---------------------------------+
| concat_ws(null,pname,page,psex) |
+---------------------------------+
| NULL                            |
| NULL                            |
| NULL                            |
| NULL                            |
| NULL                            |
| NULL                            |
| NULL                            |
| NULL                            |
| NULL                            |
| NULL                            |
| NULL                            |
| NULL                            |
+---------------------------------+


group_concat()函數(shù)

接下來就要進(jìn)入我們本文的主題了,group_concat()函數(shù), 理解了上面兩個(gè)函數(shù)的作用和用法 就對(duì)理解group_concat()函數(shù)有很大幫助了!

功能:將group by產(chǎn)生的同一個(gè)分組中的值連接起來募强,返回一個(gè)字符串結(jié)果株灸。

語法:group_concat( [distinct] 要連接的字段 [order by 排序字段 asc/desc ] [separator '分隔符'] )

注意: 中括號(hào)是可選的

分析: 通過使用distinct可以排除重復(fù)值;如果希望對(duì)結(jié)果中的值進(jìn)行排序擎值,可以使用order by子句慌烧;separator是一個(gè)字符串值,缺省為一個(gè)逗號(hào)鸠儿。

以下我準(zhǔn)備了幾個(gè)案例 小伙伴們可以選擇性的去閱讀 并且把代碼復(fù)制到MySQL中執(zhí)行以下就可以知道用法了!

重點(diǎn)注意

  1. group_concat只有與group by語句同時(shí)使用才能產(chǎn)生效果 所以使用 GROUP_CONCAT()函數(shù)必須對(duì)源數(shù)據(jù)進(jìn)行分組屹蚊,否則所有數(shù)據(jù)會(huì)被合并成一行
  2. 需要將拼接的結(jié)果去重的話,可與DISTINCT結(jié)合使用即可
案例1

需求: 比如我們要查在重慶的有哪些人? 并且把這些人的名字用 '-' 字符分隔開 然后顯示出來, SQL語句如下

#--這里就用到了 : 取出重復(fù)进每、顯示排序汹粤、 定義分隔字符
select 
    paddr,
    group_concat(distinct pname order by pname desc separator '-') as '人' 
from per 
group by paddr;

#--結(jié)果為:
+--------+----------------------------+
| paddr  | 人                         |
+--------+----------------------------+
| 上海   | 趙小麗-張良-張文軍         |
| 北京   | 王小華-張三                |
| 成都   | 劉婷                       |
| 海南   | 謝濤                       |
| 貴州   | 王建軍                     |
| 貴陽   | 黎記                       |
| 重慶   | 羅敏-張建新-劉小亞         |
+--------+----------------------------+

#--有多個(gè)的自然會(huì)被用字符分隔連接起來,只有一個(gè)人的就沒有什么變化!直接顯示

案例2

需求: 比如我們要查在重慶的有哪些人? 并且把這些人的名字用逗號(hào)隔開,

以上需求跟上面的案例1 差不多 我們就加一個(gè)效果, 也就是顯示出來的名字前面把id號(hào) 也加上

#--顯示出來每一個(gè)名字所對(duì)應(yīng)的id號(hào)  這里我們結(jié)合了group_concat()函數(shù) 和 concat_ws()函數(shù), 

select 
    paddr,
    group_concat(concat_ws('-',id,pname) order by id asc) as '人' 
from per 
group by paddr;

#--顯示結(jié)果
+--------+-----------------------------------+
| paddr  | 人                                |
+--------+-----------------------------------+
| 上海   | 2-張文軍,9-張良,11-趙小麗         |
| 北京   | 1-王小華,12-張三                  |
| 成都   | 5-劉婷                            |
| 海南   | 8-謝濤                            |
| 貴州   | 7-王建軍                          |
| 貴陽   | 10-黎記                           |
| 重慶   | 3-羅敏,4-張建新,6-劉小亞          |
+--------+-----------------------------------+

注意:

  1. MySQL中函數(shù)是可以嵌套使用的
  2. 一般使用group_concat()函數(shù),必須是存在group by 分組的情況下 才能使用這個(gè)函數(shù)
案例3

我們?cè)賮砜匆粋€(gè)案例, 首先我們準(zhǔn)備以下測(cè)試數(shù)據(jù)

準(zhǔn)備一個(gè)student學(xué)生表田晚、MySQL代碼如下

#-- student
CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,   #--id
  `stuName` varchar(22) DEFAULT NULL,     #--學(xué)生姓名
  `course` varchar(22) DEFAULT NULL,      #--學(xué)習(xí)科目
  `score` int(11) DEFAULT NULL,           #--學(xué)分
  PRIMARY KEY (`id`)                      #--設(shè)置主鍵
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;  #--設(shè)置表引擎  自動(dòng)遞增起始值 默認(rèn)編碼格式

-- ----------------------------
-- 插入以下數(shù)據(jù)
-- ----------------------------
INSERT INTO `student`(stuName,course,score) VALUES ('張三', '語文', '91');
INSERT INTO `student`(stuName,course,score) VALUES ('張三', '數(shù)學(xué)', '90');
INSERT INTO `student`(stuName,course,score) VALUES ('張三', '英語', '87');
INSERT INTO `student`(stuName,course,score) VALUES ('李四', '語文', '79');
INSERT INTO `student`(stuName,course,score) VALUES ('李四', '數(shù)學(xué)', '95');
INSERT INTO `student`(stuName,course,score) VALUES ('李四', '英語', '80');
INSERT INTO `student`(stuName,course,score) VALUES ('王五', '語文', '77');
INSERT INTO `student`(stuName,course,score) VALUES ('王五', '數(shù)學(xué)', '81');
INSERT INTO `student`(stuName,course,score) VALUES ('王五', '英語', '89');


#--建立好之后 數(shù)據(jù)如下顯示:
mysql> select * from student;
+----+---------+--------+-------+
| id | stuName | course | score |
+----+---------+--------+-------+
| 10 | 張三    | 語文   |    91 |
| 11 | 張三    | 數(shù)學(xué)   |    90 |
| 12 | 張三    | 英語   |    87 |
| 13 | 李四    | 語文   |    79 |
| 14 | 李四    | 數(shù)學(xué)   |    95 |
| 15 | 李四    | 英語   |    80 |
| 16 | 王五    | 語文   |    77 |
| 17 | 王五    | 數(shù)學(xué)   |    81 |
| 18 | 王五    | 英語   |    89 |
+----+---------+--------+-------+


建立好表和數(shù)據(jù)之后 我們就來繼續(xù)使用group_concat()函數(shù) 加深以下印象!

需求1: 以stuName學(xué)生名稱分組嘱兼,把得分?jǐn)?shù)score字段的值打印在一行,逗號(hào)分隔(默認(rèn)) SQL如下

select stuName, GROUP_CONCAT(score) as '當(dāng)前這個(gè)學(xué)生的得分?jǐn)?shù)' from student GROUP BY stuName;

#--運(yùn)行結(jié)果如下
mysql> select stuName, GROUP_CONCAT(score) as '當(dāng)前這個(gè)學(xué)生的得分?jǐn)?shù)' from student GROUP BY stuName;
+---------+--------------------------------+
| stuName | 當(dāng)前這個(gè)學(xué)生的得分?jǐn)?shù)           |
+---------+--------------------------------+
| 張三    | 91,90,87                       |
| 李四    | 79,95,80                       |
| 王五    | 77,81,89                       |
+---------+--------------------------------+

需求2: 那么根據(jù)上面的結(jié)果 我們看到分?jǐn)?shù)是出來了 但是不知道是什么科目分?jǐn)?shù) 那么我們還要把科目也連起來顯示,并且分?jǐn)?shù)還是從小到大,我們應(yīng)該怎么做呢 ? 其實(shí)很簡單的啦 SQL如下

select stuName, GROUP_CONCAT(concat_ws('=',course,score) order by score asc) as '當(dāng)前這個(gè)學(xué)生的得分?jǐn)?shù)' from student GROUP BY stuName;

#--執(zhí)行結(jié)果如下
+---------+--------------------------------+
| stuName | 當(dāng)前這個(gè)學(xué)生的得分?jǐn)?shù)           |
+---------+--------------------------------+
| 張三    | 英語=87,數(shù)學(xué)=90,語文=91        |
| 李四    | 語文=79,英語=80,數(shù)學(xué)=95        |
| 王五    | 語文=77,數(shù)學(xué)=81,英語=89        |
+---------+--------------------------------+
#-- 這樣顯示是不是覺得更加清楚了呢! 

需求3: 這里再給小伙伴深入一個(gè)問題 那么我們現(xiàn)在要查詢出 語文、數(shù)學(xué)盒蟆、外語 三門課的最低分,還有哪個(gè)學(xué)生考的踢涌? 現(xiàn)在應(yīng)該怎么寫呢?

==[方法1]==


#--首先我們可以把這個(gè)問題拆分成兩個(gè)部分
#--1.就是找出語文、數(shù)學(xué)序宦、外語 三門課的最低分 這一步還是比較簡單的我們可以使用分組查詢就可以解決

#--分析問題后得出SQL方案 按照科目進(jìn)行分組查詢  然后使用聚合函數(shù)篩選出最小的得分?jǐn)?shù), 顯示對(duì)應(yīng)科目字段 這樣就得出了三門課的最低分

SELECT min(score),course FROM student GROUP BY course;
#--那么查詢出的結(jié)果如下
+------------+--------+
| min(score) | course |
+------------+--------+
|         81 | 數(shù)學(xué)   |
|         80 | 英語   |
|         77 | 語文   |
+------------+--------+

#--那么接下來我們要考慮的是如何找到是哪個(gè)學(xué)生考的!?
#--這里我們可以使用in() 的包含+ 子查詢的方式來 根據(jù)上面SQL的結(jié)果 來進(jìn)行匹配包含查詢 學(xué)生名 
SELECT stuName,score,course from student where (score,course) in(SELECT min(score),course FROM student GROUP BY course);

#--結(jié)果如下
+---------+-------+--------+
| stuName | score | course |
+---------+-------+--------+
| 李四    |    80 | 英語   |
| 王五    |    77 | 語文   |
| 王五    |    81 | 數(shù)學(xué)   |
+---------+-------+--------+


問題分析

  1. 這里的重點(diǎn)就在于子查詢的使用 上面已經(jīng)用一句SQL查詢出了 三門課的最低分和科目 那么我們就可以列用這個(gè)結(jié)果集來 當(dāng)做另外一句SQL所要查詢條件 !
  2. where 后面跟的是一個(gè)圓括號(hào) 里面寫的是 分?jǐn)?shù)和科目兩個(gè)字段睁壁,用來匹配in() 里面的子查詢結(jié)果 可能這里有些新手小伙伴并沒有見過這樣寫 現(xiàn)在應(yīng)該清楚了

==[方法2]==


#--我們也可以用以下SQL語句來實(shí)現(xiàn) ,性能上比上面好一點(diǎn)點(diǎn)!
SELECT  g.`id`,g.`course`,g.`score`,g.`stuName`FROM (SELECT course, SUBSTRING_INDEX(GROUP_CONCAT(score ORDER BY score ASC),   ',',1) AS score FROM student GROUP BY course) AS t LEFT JOIN student AS g ON (t.course = g.`course` AND t.score = g.`score`)
    



#--小提示:SUBSTRING_INDEX() 函數(shù)是提取的連接字符中的第一個(gè)


#--簡單的說 先連接好分?jǐn)?shù)字段中的得分默認(rèn)用逗號(hào) 再從分?jǐn)?shù)連接字符中提取第一個(gè)出來, 
#--首先我們要得到每一個(gè)科目中最小的分?jǐn)?shù) 我們可以分析出如下SQL,  
#--這里的分組條件還是以科目進(jìn)行分組, 分組之后還是GROUP_CONCAT()函數(shù)用逗號(hào)連接起相對(duì)應(yīng)的所有分?jǐn)?shù),然后用SUBSTRING_INDEX()函數(shù)提取連接字符中的第一個(gè)字符作為結(jié)果
SELECT course,SUBSTRING_INDEX(GROUP_CONCAT(score ORDER BY score ASC),',',1) AS score FROM student GROUP BY course;
#--結(jié)果如下
+--------+-------+
| course | score |
+--------+-------+
| 數(shù)學(xué)   | 81    |
| 英語   | 80    |
| 語文   | 77    |
+--------+-------+

#--我們可以把這個(gè)結(jié)果 想象成一張?zhí)摂M表取一個(gè)別名 t, 現(xiàn)在t這個(gè)是一個(gè)臨時(shí)的表挨厚,我們要查詢id,科目,分?jǐn)?shù),姓名, 就在前面加上需要的字段,注意別名
#--然后再使用左連接篩選出 對(duì)應(yīng)的結(jié)果
SELECT  g.`id`,g.`course`,g.`score`,g.`stuName`FROM
(SELECT course,SUBSTRING_INDEX(GROUP_CONCAT(score ORDER BY score ASC),',',1) AS score FROM student GROUP BY course) as t
LEFT JOIN student AS g ON (t.course = g.`course` AND t.score = g.`score`)  #--left join 來顯示出符合條件的結(jié)果 也就是用上面查詢出來的結(jié)果來對(duì)應(yīng)條件

#--結(jié)果如下
+------+--------+-------+---------+
| id   | course | score | stuName |
+------+--------+-------+---------+
|   15 | 英語   |    80 | 李四    |
|   16 | 語文   |    77 | 王五    |
|   17 | 數(shù)學(xué)   |    81 | 王五    |
+------+--------+-------+---------+



    
案例4

我們來簡單的準(zhǔn)備一個(gè)商品表吧 , 代碼如下

#-- goods
CREATE TABLE `goods` (
  `id` int(11) NOT NULL AUTO_INCREMENT,   #--id
  `price` varchar(22) DEFAULT NULL,       #--商品價(jià)格
  `goods_name` varchar(22) DEFAULT NULL,  #--商品名稱
  PRIMARY KEY (`id`)                      
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;  #--設(shè)置表引擎  自動(dòng)遞增起始值 默認(rèn)編碼格式

-- ----------------------------
-- 插入以下數(shù)據(jù)
-- ----------------------------
INSERT INTO `goods`(price,goods_name) VALUES (10.00, '皮包');
INSERT INTO `goods`(price,goods_name) VALUES (20.00, '圍巾');
INSERT INTO `goods`(price,goods_name) VALUES (30.00, '圍巾');
INSERT INTO `goods`(price,goods_name) VALUES (40.00, '游戲機(jī)');
INSERT INTO `goods`(price,goods_name) VALUES (60.00, '皮包');
INSERT INTO `goods`(price,goods_name) VALUES (80.00, '游戲機(jī)');
INSERT INTO `goods`(price,goods_name) VALUES (220.00, '游戲機(jī)');
INSERT INTO `goods`(price,goods_name) VALUES (780.00, '圍巾');
INSERT INTO `goods`(price,goods_name) VALUES (560.00, '游戲機(jī)');
INSERT INTO `goods`(price,goods_name) VALUES (30.00, '皮包');


需求1: 以 商品名稱分組堡僻,把price字段的值在一行打印出來,分號(hào)分隔

select goods_name,group_concat(price) from goods group by goods_name;

需求2: 以 商品名稱分組疫剃,把price字段的值在一行打印出來钉疫,分號(hào)分隔 并且去除重復(fù)冗余的價(jià)格字段的值

select goods_name,group_concat(distinct price) from goods group by goods_name;

需求3: 以 商品名稱分組,把price字段的值在一行打印出來巢价,分號(hào)分隔 去除重復(fù)冗余的價(jià)格字段的值 并且排序 從小到大

select goods_name,group_concat(distinct price order by price desc) from goods group by goods_name;  #--錯(cuò)誤的

select goods_name,group_concat(distinct price order by price+1 desc) from goods group by goods_name; #--正確的


#--注意以上存在隱式數(shù)據(jù)類型轉(zhuǎn)換 如果不這樣轉(zhuǎn)換排序出來的結(jié)果是錯(cuò)誤的   , 因?yàn)槲冶4鎝rice價(jià)格的字段是varchar類型的
案例5

我們?cè)俳Y(jié)合group_concat()函數(shù)來做一個(gè)多表查詢的案例

準(zhǔn)備 三張 測(cè)試數(shù)據(jù)表: 用戶表[user]牲阁、水果表[fruit]固阁、用戶喜歡哪些水果的表[user_like]

首先 建立用戶表[user] SQL語句代碼如下

#-- user
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,   #--id
  `username` varchar(22) DEFAULT NULL,    #--用戶名
  PRIMARY KEY (`id`)                      
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;  #--設(shè)置表引擎  自動(dòng)遞增起始值 默認(rèn)編碼格式

#--插入測(cè)試數(shù)據(jù)
INSERT INTO `user`(username) VALUES ('張三');
INSERT INTO `user`(username) VALUES ('李四');
INSERT INTO `user`(username) VALUES ('王文玉');


2.png

建立水果表[fruit] SQL語句代碼如下

#-- fruit
CREATE TABLE `fruit` (
  `id` int(11) NOT NULL AUTO_INCREMENT,   #--id
  `fruitname` varchar(22) DEFAULT NULL,   #--水果名稱
  PRIMARY KEY (`id`)                      
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;  #--設(shè)置表引擎  自動(dòng)遞增起始值 默認(rèn)編碼格式


#--插入測(cè)試數(shù)據(jù)
INSERT INTO `fruit`(fruitname) VALUES ('西瓜');
INSERT INTO `fruit`(fruitname) VALUES ('蘋果');
INSERT INTO `fruit`(fruitname) VALUES ('芒果');
INSERT INTO `fruit`(fruitname) VALUES ('梨');
INSERT INTO `fruit`(fruitname) VALUES ('葡萄');


3.png

建立 用戶喜愛表 [user_like]

但是建立這個(gè)表的時(shí)候 跟前面兩個(gè)表有所不同,小伙們們首先要搞清楚 這個(gè)表是一個(gè)什么用來干啥的表

分析清楚這個(gè)表的關(guān)系城菊, 因?yàn)槭怯脩粝矚g哪些水果的表 那么 一個(gè)水果可以被多個(gè)用戶所喜歡對(duì)吧? 反過來說一個(gè)用戶也可以喜歡多個(gè)水果吧 對(duì)吧 那么這里是一個(gè)什么關(guān)系呢 备燃?? 很明顯是一個(gè) 多對(duì)多的關(guān)系!

所以建立這個(gè)表 我們就可以使用 用戶的id 來對(duì)應(yīng) 水果的id 就可以實(shí)現(xiàn)一個(gè)中間連接多對(duì)多的表了

SQL語句代碼如下:

#-- fruit
CREATE TABLE `user_like` (
  `id` int(11) NOT NULL AUTO_INCREMENT,   #--id
  `user_id` int,                          #--用戶的id號(hào)
  `fruit_id` int,                         #--水果的id號(hào)
  CONSTRAINT user_like PRIMARY KEY (id,user_id,fruit_id)  #--定義聯(lián)合主鍵  讓每一條記錄唯一
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;  #--設(shè)置表引擎  自動(dòng)遞增起始值 默認(rèn)編碼格式


#--測(cè)試數(shù)據(jù)
INSERT INTO `user_like`(user_id,fruit_id) VALUES (1,1);  #--這就代表用戶表中id號(hào)為1的用戶  喜歡fruit表中id號(hào)為1的水果
INSERT INTO `user_like`(user_id,fruit_id) VALUES (1,2);  #--這就代表用戶表中id號(hào)為1的用戶  喜歡fruit表中id號(hào)為2的水果
INSERT INTO `user_like`(user_id,fruit_id) VALUES (1,3);  #--這就代表用戶表中id號(hào)為1的用戶  喜歡fruit表中id號(hào)為3的水果
INSERT INTO `user_like`(user_id,fruit_id) VALUES (2,3);  #--這就代表用戶表中id號(hào)為2的用戶  喜歡fruit表中id號(hào)為3的水果
INSERT INTO `user_like`(user_id,fruit_id) VALUES (2,4);  #--這就代表用戶表中id號(hào)為2的用戶  喜歡fruit表中id號(hào)為4的水果
INSERT INTO `user_like`(user_id,fruit_id) VALUES (2,5);  #--這就代表用戶表中id號(hào)為2的用戶  喜歡fruit表中id號(hào)為5的水果
INSERT INTO `user_like`(user_id,fruit_id) VALUES (3,5);  #--這就代表用戶表中id號(hào)為3的用戶  喜歡fruit表中id號(hào)為5的水果
INSERT INTO `user_like`(user_id,fruit_id) VALUES (3,1);  #--這就代表用戶表中id號(hào)為3的用戶  喜歡fruit表中id號(hào)為1的水果
INSERT INTO `user_like`(user_id,fruit_id) VALUES (3,2);  #--這就代表用戶表中id號(hào)為3的用戶  喜歡fruit表中id號(hào)為2的水果
#--  以此類推...

4.png

好了 現(xiàn)在數(shù)據(jù) 和 表我們都已經(jīng)準(zhǔn)備好了 , 那么 接下來 我們就要開始進(jìn)行 GROUP_CONCAT()函數(shù)的使用了

需求: 查出每個(gè)用戶喜歡的水果都有哪些!

#--查詢SQL如下
select u.username,group_concat(f.fruitname) from user_like as c inner join user as u on c.user_id=u.id inner join  fruit as f on c.fruit_id=f.id group by c.user_id; 

#--結(jié)果如下
+-----------+---------------------------+
| username  | group_concat(f.fruitname) |
+-----------+---------------------------+
| 張三      | 芒果,蘋果                 |
| 李四      | 梨,芒果,葡萄              |
| 王文玉    | 西瓜,葡萄,蘋果            |
+-----------+---------------------------+



end.jpg
bilibili_gif.gif

如果我的博客對(duì)你有幫助凌唬、如果你喜歡我的博客內(nèi)容并齐,請(qǐng) “點(diǎn)贊” “評(píng)論” “收藏” 一鍵三連哦!


如果以上內(nèi)容有任何錯(cuò)誤或者不準(zhǔn)確的地方客税,歡迎在下面 ?? 留個(gè)言指出况褪、或者你有更好的想法,歡迎一起交流學(xué)習(xí)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末更耻,一起剝皮案震驚了整個(gè)濱河市测垛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秧均,老刑警劉巖食侮,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異目胡,居然都是意外死亡锯七,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門誉己,熙熙樓的掌柜王于貴愁眉苦臉地迎上來起胰,“玉大人,你說我怎么就攤上這事巫延。” “怎么了地消?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵炉峰,是天一觀的道長。 經(jīng)常有香客問我脉执,道長疼阔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任半夷,我火速辦了婚禮婆廊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘巫橄。我一直安慰自己淘邻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布湘换。 她就那樣靜靜地躺著宾舅,像睡著了一般统阿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上筹我,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天扶平,我揣著相機(jī)與錄音,去河邊找鬼蔬蕊。 笑死结澄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的岸夯。 我是一名探鬼主播麻献,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼囱修!你這毒婦竟也來了赎瑰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤破镰,失蹤者是張志新(化名)和其女友劉穎餐曼,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鲜漩,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡源譬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了孕似。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片踩娘。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖喉祭,靈堂內(nèi)的尸體忽然破棺而出养渴,到底是詐尸還是另有隱情,我是刑警寧澤泛烙,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布理卑,位于F島的核電站,受9級(jí)特大地震影響蔽氨,放射性物質(zhì)發(fā)生泄漏藐唠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一鹉究、第九天 我趴在偏房一處隱蔽的房頂上張望宇立。 院中可真熱鬧,春花似錦自赔、人聲如沸妈嘹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蟋滴。三九已至染厅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間津函,已是汗流浹背肖粮。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尔苦,地道東北人涩馆。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像允坚,于是被迫代替她去往敵國和親魂那。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354