sql group_concat以及其中的获取反向结果

时间:2018-08-07 12:59:00

标签: sql where group-concat

查询很麻烦。

如果我运行此程序(仅第一学期):

SELECT subject.name as subject, GROUP_CONCAT(evaluations_mark.note) as mark 
FROM evaluations_mark 
LEFT JOIN subject ON evaluations_mark.subject_id = subject.subject_id
LEFT JOIN user ON evaluations_mark.user_id = user.user_id
WHERE evaluations_mark.number_exam = 1 AND evaluations_mark.user_id = 28265
AND subject.print_visible='1' 
AND subject.number_exam = '4' 
GROUP BY evaluations_mark.subject_id

我得到的结果很好:

+--------------------+-----+
| Lengua             | SA  |
| Matematica         | SA  |
| Ciencias Sociales  | MSA |
| Ciencias Naturales | MSA |
| Italiano           | MSA |
| Ingles             | SA  |<--RIGHT!
+--------------------+-----+

如果我运行其他查询:

SELECT subject.name as subject, GROUP_CONCAT(evaluations_mark.note) as mark 
FROM evaluations_mark 
LEFT JOIN subject ON evaluations_mark.subject_id = subject.subject_id
LEFT JOIN user ON evaluations_mark.user_id = user.user_id
WHERE evaluations_mark.number_exam = 2 AND evaluations_mark.user_id = 28265
AND subject.print_visible='1' 
AND subject.number_exam = '4' 
GROUP BY evaluations_mark.subject_id

我得到的结果也很好(仅适用于第二学期):

+--------------------+-----+
| Lengua             | SA  |
| Matematica         | SA  |
| Ciencias Sociales  | SA  |
| Ciencias Naturales | MSA |
| Italiano           | MSA |
| Ingles             | MSA |<--RIGHT!
+--------------------+-----+

现在,问题终于来了。如果我运行该死的查询:

SELECT subject.name as subject, GROUP_CONCAT(evaluations_mark.note) as mark 
FROM evaluations_mark 
LEFT JOIN subject ON evaluations_mark.subject_id = subject.subject_id
LEFT JOIN user ON evaluations_mark.user_id = user.user_id
WHERE evaluations_mark.number_exam IN (1,2) AND evaluations_mark.user_id = 28265
AND subject.print_visible='1' 
AND subject.number_exam = '4' 
GROUP BY evaluations_mark.subject_id

我得到两个倒数的记录(两个学期):

+--------------------+-----+-----+
| Lengua             | SA  | SA  |
| Matematica         | SA  | SA  |
| Ciencias Sociales  | MSA | SA  |
| Ciencias Naturales | MSA | MSA |
| Italiano           | MSA | MSA |
| Ingles             | MSA | SA  |******* <<--WRONG! IT'S INVERTED!
+--------------------+-----+-----+

第一栏:主题 第二列:第一学期(第一个结果) 第三栏:第二个学期(第二个结果)

这到底是为什么呢?预先感谢!

EDIT2:将3张图片替换为文字。

EDIT3:这是表结构

TABLE `evaluations_mark` (
  `mark_id` int(13) NOT NULL,
  `note` varchar(225) NOT NULL,
  `comments` text NOT NULL,
  `subject_id` int(13) NOT NULL,
  `course_id` int(13) NOT NULL,
  `user_id` int(13) NOT NULL,
  `evaluation_id` int(13) NOT NULL,
  `number_exam` int(2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

TABLE `subject` (
  `subject_id` int(6) NOT NULL,
  `name` varchar(50) NOT NULL,
  `course_id` int(6) NOT NULL,
  `teacher_id` int(6) NOT NULL,
  `load_type` varchar(20) NOT NULL,
  `hours` int(11) NOT NULL,
  `area_id` int(2) NOT NULL,
  `active` tinyint(1) NOT NULL,
  `number_exam` int(6) NOT NULL,
  `parent` int(5) NOT NULL,
  `print_visible` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

编辑4:从两个表中添加了所需的内容

评价标记表:

mark_id     note    comments    subject_id  course_id   1   user_id     evaluation_id   number_exam     
4363    SA      87  8   28265   0   1   
4892    MSA     84  8   28265   0   2   
1078    SA      85  8   28265   0   1   
3646    MSA     88  8   28265   0   1   
2634    MSA     89  8   28265   0   1   
125 SA      80  8   28265   0   1   
147 MSA     82  8   28265   0   1   
1430    MSA     84  8   28265   0   1   
169 MSA     83  8   28265   0   1   
3753    SA      80  8   28265   0   2   
3510    MSA     85  8   28265   0   2   
191 SA      81  8   28265   0   1   
3775    SA      81  8   28265   0   2   
6858    MSA     86  8   28265   0   1   
3279    MSA     83  8   28265   0   2   
3797    SA      82  8   28265   0   2   

主题表:

subject_id  name    course_id   teacher_id  load_type   hours   area_id     active  number_exam     parent  print_visible   
80  Lengua y Literatura 8   0   1   4   2   0   4   0   1   
81  Matemática  8   0   1   4   2   0   4   0   1   
82  Ciencias Sociales   8   0   1   4   2   0   4   0   1   
83  Ciencias Naturales  8   0   1   4   2   0   4   0   1   
84  Italiano    8   0   2   5   2   0   4   0   1   
85  Inglés  8   0   2   4   2   0   4   0   1   
86  Expresion Plástica  8   0   2   3   2   0   2   0   1   
87  Música  8   0   2   2   2   0   2   0   1   
88  Informática 8   0   2   3   2   0   2   0   1   
89  Educación Física    8   0   2   2   2   0   2   0   1   

编辑4:我标记了对与错。

1 个答案:

答案 0 :(得分:0)

在我看来,LEFT JOINuser在此查询中是多余的,因为该表中的任何列均未以任何方式引用。您可以将查询简化为

SELECT subject.name as subject, GROUP_CONCAT(evaluations_mark.note) as mark 
FROM evaluations_mark 
LEFT JOIN subject ON evaluations_mark.subject_id = subject.subject_id
WHERE evaluations_mark.number_exam IN (1,2) AND evaluations_mark.user_id = 28265
AND subject.print_visible='1' 
AND subject.number_exam = '4' 
GROUP BY evaluations_mark.subject_id

此外,您的结果肯定应该仅包含两列subjectmark。在第二栏中,您可以找到多个结果(字母组),以逗号分隔。

我根据您的信息创建了一个小样演示 http://rextester.com/DXAQIP21690 (实际测试数据仍然缺失!)来说明我的观点,即输出仅包含两列。也许您可以进一步指导我们您的问题所在?

编辑1
我添加了您提供的示例数据: http://rextester.com/OVSL70192 ,随时随地进行演示。

请告诉我们:您的期望输出是什么? “结果倒置”是什么意思?我不能跟随你。

Edit2
好的,您对“错误”的评论进一步阐明了您的问题。 在我最新的演示版本 http://rextester.com/XWSO90046 中,您将找到两个输出列mark1mark2

SELECT s.name as subject, 
  group_concat(CASE e.number_exam WHEN 1 THEN e.note END)  as mark1,
  group_concat(CASE e.number_exam WHEN 2 THEN e.note END)  as mark2 
FROM evaluations_mark e 
LEFT JOIN subject s ON e.subject_id = s.subject_id
WHERE e.number_exam IN (1,2) AND e.user_id = 28265
  AND s.print_visible='1'    AND s.number_exam = '4' 
GROUP BY e.subject_id

结果:

subject              mark1   mark2
Lengua y Literatura  SA      SA
Matemática           SA      SA
Ciencias Sociales    MSA     SA
Ciencias Naturales   MSA     MSA
Italiano             MSA     MSA
Inglés               SA      MSA

原始查询中的group_concat函数没有为其指定任何order by子句,因此内部元素的顺序未定义(即任意!)。您可以通过在ORDER BY子句中使用GROUP_CONCAT来改善这种情况,如下所示:

---顺便说一句,这是用于OP的代码(请参阅下面的评论)---

OP接受的代码:

SELECT s.name as subject, 
  GROUP_CONCAT(e.note ORDER BY e.number_exam) as mark 
FROM evaluations_mark e
LEFT JOIN subject s ON e.subject_id = s.subject_id
WHERE e.number_exam IN (1,2) AND e.user_id = 28265
AND s.print_visible='1' 
AND s.number_exam = '4' 
GROUP BY e.subject_id

这会让你

subject              mark
-----------------------------
Lengua y Literatura  SA,SA
Matemática           SA,SA
Ciencias Sociales    MSA,SA
Ciencias Naturales   MSA,MSA
Italiano             MSA,MSA
Inglés               SA,MSA

请参见此处:http://rextester.com/UEZ55062,但是请注意,mark仍然只是一列

Edit3
刚刚也在phpmyadmin中进行了测试: view of listing in phpmyadmin

select version()
>> 5.1.73-1+deb6u1-log

我还在以下公共沙箱上进行了测试:https://demo.phpmyadmin.net/STABLE/db_structure.php?server=2&db=Test,它可以正常工作!使用root和空(= no!)密码登录。

上面在“ OP接受的代码”下显示的代码再次产生了以下结果:

enter image description here

Edit4
最后一点:严格来说,您还应该在查询中使用MAX(s.name) as subject, ...,因为您仅按e.subject_id分组。不过,MySql在这方面是相当(太)宽容的。