最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

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

2020-09-22 11:14 作者:極客小俊GeekerJun  | 我要投稿

極客小俊

?一個專注于web技術(shù)的80后

你不用拼過聰明人,你只需要拼過那些懶人 你就一定會超越大部分人!



前言

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

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

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



首先我們來建立一個測試的表和數(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é)一個函數(shù)叫concat()函數(shù), 這個函數(shù)非常簡單

功能:就是將多個字符串連接成一個字符串

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

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

案例1

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

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



案例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 ? ? ? ? ? ? ? ? ? ?|
?+-------------------------+
?
?#--為什么會有一條是NULL呢? ?
?#--那是因為第12條數(shù)據(jù)中的page字段為空,根據(jù)有一個字段為空結(jié)果就為NULL的理論推導(dǎo)出 查詢出的最后一條記錄為NULL!
?
?


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


concat_ws()函數(shù)

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

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

separator就是分隔符字符!

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


案例代碼:

?select concat_ws(',',pname,page,psex) from per; ?
?#--以逗號分割 結(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; ? #--錯誤的
?+---------------------------------+
?| concat_ws(null,pname,page,psex) |
?+---------------------------------+
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?| NULL ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
?+---------------------------------+
?
?


group_concat()函數(shù)

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

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

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

注意: 中括號是可選的

分析: ?通過使用distinct可以排除重復(fù)值;如果希望對結(jié)果中的值進行排序,可以使用order by子句;separator是一個字符串值,缺省為一個逗號。

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


重點注意

  1. group_concat只有與group by語句同時使用才能產(chǎn)生效果 所以使用 GROUP_CONCAT()函數(shù)必須對源數(shù)據(jù)進行分組,否則所有數(shù)據(jù)會被合并成一行

  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 ?| 人 ? ? ? ? ? ? ? ? ? ? ? ? |
?+--------+----------------------------+
?| 上海 ? | 趙小麗-張良-張文軍 ? ? ? ? |
?| 北京 ? | 王小華-張三 ? ? ? ? ? ? ? ?|
?| 成都 ? | 劉婷 ? ? ? ? ? ? ? ? ? ? ? |
?| 海南 ? | 謝濤 ? ? ? ? ? ? ? ? ? ? ? |
?| 貴州 ? | 王建軍 ? ? ? ? ? ? ? ? ? ? |
?| 貴陽 ? | 黎記 ? ? ? ? ? ? ? ? ? ? ? |
?| 重慶 ? | 羅敏-張建新-劉小亞 ? ? ? ? |
?+--------+----------------------------+
?
?#--有多個的自然會被用字符分隔連接起來,只有一個人的就沒有什么變化!直接顯示
?


案例2

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

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

?#--顯示出來每一個名字所對應(yīng)的id號 ?這里我們結(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 分組的情況下 才能使用這個函數(shù)



案例3

我們再來看一個案例, 首先我們準(zhǔn)備以下測試數(shù)據(jù)

準(zhǔn)備一個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è)置表引擎 ?自動遞增起始值 默認(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字段的值打印在一行,逗號分隔(默認(rèn)) ?SQL如下

?select stuName, GROUP_CONCAT(score) as '當(dāng)前這個學(xué)生的得分?jǐn)?shù)' from student GROUP BY stuName;
?
?#--運行結(jié)果如下
?mysql> select stuName, GROUP_CONCAT(score) as '當(dāng)前這個學(xué)生的得分?jǐn)?shù)' from student GROUP BY stuName;
?+---------+--------------------------------+
?| stuName | 當(dāng)前這個學(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)該怎么做呢 ? 其實很簡單的啦 SQL如下

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


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

[方法1]

?
?#--首先我們可以把這個問題拆分成兩個部分
?#--1.就是找出語文、數(shù)學(xué)、外語 三門課的最低分 這一步還是比較簡單的我們可以使用分組查詢就可以解決
?
?#--分析問題后得出SQL方案 按照科目進行分組查詢 ?然后使用聚合函數(shù)篩選出最小的得分?jǐn)?shù), 顯示對應(yīng)科目字段 這樣就得出了三門課的最低分
?
?SELECT min(score),course FROM student GROUP BY course;
?#--那么查詢出的結(jié)果如下
?+------------+--------+
?| min(score) | course |
?+------------+--------+
?| ? ? ? ? 81 | 數(shù)學(xué) ? |
?| ? ? ? ? 80 | 英語 ? |
?| ? ? ? ? 77 | 語文 ? |
?+------------+--------+
?
?#--那么接下來我們要考慮的是如何找到是哪個學(xué)生考的!?
?#--這里我們可以使用in() 的包含+ 子查詢的方式來 根據(jù)上面SQL的結(jié)果 來進行匹配包含查詢 學(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. 這里的重點就在于子查詢的使用 上面已經(jīng)用一句SQL查詢出了 三門課的最低分和科目 ?那么我們就可以列用這個結(jié)果集來 當(dāng)做另外一句SQL所要查詢條件 !

  2. where 后面跟的是一個圓括號 里面寫的是 分?jǐn)?shù)和科目兩個字段,用來匹配in() 里面的子查詢結(jié)果 ?可能這里有些新手小伙伴并沒有見過這樣寫 現(xiàn)在應(yīng)該清楚了

[方法2]

?
?#--我們也可以用以下SQL語句來實現(xià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ù)是提取的連接字符中的第一個
?
?
?#--簡單的說 先連接好分?jǐn)?shù)字段中的得分默認(rèn)用逗號 再從分?jǐn)?shù)連接字符中提取第一個出來,
?#--首先我們要得到每一個科目中最小的分?jǐn)?shù) 我們可以分析出如下SQL, ?
?#--這里的分組條件還是以科目進行分組, 分組之后還是GROUP_CONCAT()函數(shù)用逗號連接起相對應(yīng)的所有分?jǐn)?shù),然后用SUBSTRING_INDEX()函數(shù)提取連接字符中的第一個字符作為結(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 ? ?|
?+--------+-------+
?
?#--我們可以把這個結(jié)果 想象成一張?zhí)摂M表取一個別名 t, 現(xiàn)在t這個是一個臨時的表,我們要查詢id,科目,分?jǐn)?shù),姓名, 就在前面加上需要的字段,注意別名
?#--然后再使用左連接篩選出 對應(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é)果來對應(yīng)條件
?
?#--結(jié)果如下
?+------+--------+-------+---------+
?| id ? | course | score | stuName |
?+------+--------+-------+---------+
?| ? 15 | 英語 ? | ? ?80 | 李四 ? ?|
?| ? 16 | 語文 ? | ? ?77 | 王五 ? ?|
?| ? 17 | 數(shù)學(xué) ? | ? ?81 | 王五 ? ?|
?+------+--------+-------+---------+
?
?
?
? ? ?


案例4

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

?#-- goods
?CREATE TABLE `goods` (
? ?`id` int(11) NOT NULL AUTO_INCREMENT, ? #--id
? ?`price` varchar(22) DEFAULT NULL, ?? ? ?#--商品價格
? ?`goods_name` varchar(22) DEFAULT NULL, ?#--商品名稱
? ?PRIMARY KEY (`id`) ? ? ??
?) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; ?#--設(shè)置表引擎 ?自動遞增起始值 默認(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, '游戲機');
?INSERT INTO `goods`(price,goods_name) VALUES (60.00, '皮包');
?INSERT INTO `goods`(price,goods_name) VALUES (80.00, '游戲機');
?INSERT INTO `goods`(price,goods_name) VALUES (220.00, '游戲機');
?INSERT INTO `goods`(price,goods_name) VALUES (780.00, '圍巾');
?INSERT INTO `goods`(price,goods_name) VALUES (560.00, '游戲機');
?INSERT INTO `goods`(price,goods_name) VALUES (30.00, '皮包');
?
?

需求1: 以 商品名稱分組,把price字段的值在一行打印出來,分號分隔

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

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

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

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

?select goods_name,group_concat(distinct price order by price desc) from goods group by goods_name; ?#--錯誤的
?
?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é)果是錯誤的 ? , 因為我保存price價格的字段是varchar類型的



案例5

我們再結(jié)合group_concat()函數(shù)來做一個多表查詢的案例

準(zhǔn)備 三張 測試數(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è)置表引擎 ?自動遞增起始值 默認(rèn)編碼格式
?
?#--插入測試數(shù)據(jù)
?INSERT INTO `user`(username) VALUES ('張三');
?INSERT INTO `user`(username) VALUES ('李四');
?INSERT INTO `user`(username) VALUES ('王文玉');
?


?

建立水果表[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è)置表引擎 ?自動遞增起始值 默認(rèn)編碼格式
?
?
?#--插入測試數(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 ('葡萄');
?
?


建立 用戶喜愛表 [user_like] ?

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

分析清楚這個表的關(guān)系, ?因為是用戶喜歡哪些水果的表 那么 一個水果可以被多個用戶所喜歡對吧? ?反過來說一個用戶也可以喜歡多個水果吧 對吧 那么這里是一個什么關(guān)系呢 ?? ?很明顯是一個 多對多的關(guān)系! ?

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

SQL語句代碼如下:

?#-- fruit
?CREATE TABLE `user_like` (
? ?`id` int(11) NOT NULL AUTO_INCREMENT, ? #--id
? ?`user_id` int, ?? ? ? ? ? ?#--用戶的id號
? ?`fruit_id` int, ?? ? ? ? ? ?#--水果的id號
? ?CONSTRAINT user_like PRIMARY KEY (id,user_id,fruit_id) ?#--定義聯(lián)合主鍵 ?讓每一條記錄唯一
?) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; ?#--設(shè)置表引擎 ?自動遞增起始值 默認(rèn)編碼格式
?
?
?#--測試數(shù)據(jù)
?INSERT INTO `user_like`(user_id,fruit_id) VALUES (1,1); ?#--這就代表用戶表中id號為1的用戶 ?喜歡fruit表中id號為1的水果
?INSERT INTO `user_like`(user_id,fruit_id) VALUES (1,2); ?#--這就代表用戶表中id號為1的用戶 ?喜歡fruit表中id號為2的水果
?INSERT INTO `user_like`(user_id,fruit_id) VALUES (1,3); ?#--這就代表用戶表中id號為1的用戶 ?喜歡fruit表中id號為3的水果
?INSERT INTO `user_like`(user_id,fruit_id) VALUES (2,3); ?#--這就代表用戶表中id號為2的用戶 ?喜歡fruit表中id號為3的水果
?INSERT INTO `user_like`(user_id,fruit_id) VALUES (2,4); ?#--這就代表用戶表中id號為2的用戶 ?喜歡fruit表中id號為4的水果
?INSERT INTO `user_like`(user_id,fruit_id) VALUES (2,5); ?#--這就代表用戶表中id號為2的用戶 ?喜歡fruit表中id號為5的水果
?INSERT INTO `user_like`(user_id,fruit_id) VALUES (3,5); ?#--這就代表用戶表中id號為3的用戶 ?喜歡fruit表中id號為5的水果
?INSERT INTO `user_like`(user_id,fruit_id) VALUES (3,1); ?#--這就代表用戶表中id號為3的用戶 ?喜歡fruit表中id號為1的水果
?INSERT INTO `user_like`(user_id,fruit_id) VALUES (3,2); ?#--這就代表用戶表中id號為3的用戶 ?喜歡fruit表中id號為2的水果
?#-- ?以此類推...
?


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

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

?#--查詢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) |
?+-----------+---------------------------+
?| 張三 ? ? ?| 芒果,蘋果 ? ? ? ? ? ? ? ? |
?| 李四 ? ? ?| 梨,芒果,葡萄 ? ? ? ? ? ? ?|
?| 王文玉 ? ?| 西瓜,葡萄,蘋果 ? ? ? ? ? ?|
?+-----------+---------------------------+
?
?
?

如果喜歡話請 點贊 ?投幣 ?收藏 一鍵三連 ?

大家的支持就是我堅持下去的動力!

不要忘了?? 關(guān)注 ??哦!



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

分享到微博請遵守國家法律
曲靖市| 万盛区| 怀宁县| 台湾省| 鸡西市| 家居| 吉隆县| 扎鲁特旗| 无为县| 肥城市| 丰都县| 遵义县| 凭祥市| 礼泉县| 道孚县| 梧州市| 安仁县| 凌云县| 长沙市| 湖口县| 宁城县| 曲麻莱县| 集安市| 马公市| 静乐县| 景宁| 孝义市| 奇台县| 苏尼特左旗| 武邑县| 青海省| 太白县| 龙海市| 金塔县| 沧源| 策勒县| 墨竹工卡县| 枝江市| 沁水县| 高要市| 布尔津县|