最近帮人做了一个成绩单打印的功能,需要在成绩单上打印出成绩划分等级和具体的成绩范围,左思右想~~~在一条SQL搞定和循环多条记录拼接之间徘徊,由于时间匆忙,还是选择了简单的查询、循环、拼接。但是还是不甘心,赶紧那样做太low。于是乎,事后继续研究。
数据库中数据存格式如下:
成绩等级:
等级(point_grade)对应的数据字典:
最终要实现的效果:
先是百度各种拼接函数,挑来选去用了这俩:
语法:
GROUP_CONCAT([DISTINCT]要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator ‘分隔符’])—–à默认使用逗号分隔
支持多个列拼接在一行展示。
语法:
CONCAT_WS(separator,str1,str2,……)
将多个列使用指定字符串进行拼接成一个字符串返回。
与CONCAT(str1,str2,str3,……)的区别,当CONCAT函数中返回的任意一个字段的值为NULL时,则整个返回结果就为NULL,而当CONCAT_WS函数中任意一个字段的值为NULL时,则会自动忽略此列的值进行拼接;当CONCAT函数中返回的任意一个字段的值为’ ’时,则返回结果会将空白项拼接在字符串中返回。
实现过程:
(1)将所有的分数范围拼接在一起
SELECT
CONCAT_WS(‘-‘,m.point_min, m.point_max) AS scoreStr
FROM et_exam_grade m
WHERE m.del_flag = ‘0’
AND m.exam_id = ‘1’ ORDER BY m.point_min
效果如下:
- 将成绩范围和“分”拼接在一起,并且转为一行:
SELECT
CONCAT_WS(‘ ‘,
GROUP_CONCAT(a.scoreStr,’分’ SEPARATOR ‘,’)
) AS res
FROM (
SELECT CONCAT_WS(‘-‘, m.point_min,m.point_max) AS scoreStr,
m.id AS aId,m.point_grade AS gradea
FROM et_exam_grade m
WHERE m.del_flag = ‘0’
AND m.exam_id = ‘1’
ORDER BY m.point_min
) a, (
SELECT n.id AS bId, n.point_grade AS gradeb
FROM et_exam_grade n
WHERE n.del_flag = ‘0’
AND n.exam_id = ‘1’
ORDER BY n.point_min
) b WHERE a.aId = b.bId
效果如下:
- 将数据字典值和成绩等级对应:
SELECT CONCAT_WS(‘ ‘,GROUP_CONCAT(a.scoreStr,c.label SEPARATOR ‘,’)) as res FROM (
SELECT CONCAT_WS(‘-‘,m.point_min,m.point_max) as scoreStr,m.id as aId,m.point_grade as gradea
FROM et_exam_grade m WHERE m.del_flag =’0′ AND
m.exam_id=’1′ ORDER BY m.point_min
)a,(SELECT n.id as bId,n.point_grade as gradeb FROM et_exam_grade n WHERE n.del_flag=’0′ AND n.exam_id=’1′
ORDER BY n.point_min)b,(SELECT d.label label,d.`value` as dictVal FROM sys_dict d WHERE d.type=’score_grade’)c
WHERE a.aId = b.bId AND a.gradea = b.gradeb AND b.gradeb = c.dictVal
效果如下:
目的达成!!!注意第三步的时候去掉了‘分’的拼接,这个无所谓啦!!!
有更好的实现方式的,欢迎分享!!!!