MySQL 中可能存在或不存在的引用数据

Posted

技术标签:

【中文标题】MySQL 中可能存在或不存在的引用数据【英文标题】:Reference data that could or not exist in MySQL 【发布时间】:2013-12-26 12:02:22 【问题描述】:

我有这张桌子:

courses: id_course,name_course
users: id_user,nickname_user
teachers: id_teacher,id_course_teacher,id_user_teacher (it has a value 
just in case this teacher is in the table users)

我列出一门课程,其中包含所有教师的列表(带有辅助表):

SELECT c.name_course,group_concat(DISTINCT t.name_teacher) AS teachers 
FROM courses c
LEFT JOIN teachers t ON t.id_course_teacher=c.id_course
WHERE c.id_course='1';
It shows: Course 1: Teacher 1, Teacher 2, Teacher 5.

其中一些老师在另一个表 users 中有个人资料,我还想显示老师的昵称(如果存在):

Course 1: Teacher 1, Teacher 2 (nickname), Teacher 5.

我试过了,但我无法将昵称引用给老师:

SELECT name_course,group_concat(DISTINCT t.name_teacher) AS teachers,
                   group_concat(DISTINCT u.nickname_user) AS nickname 
FROM courses c
LEFT JOIN teachers t ON t.id_course_teacher=c.id_course,
LEFT JOIN users u ON t.id_user_teacher=u.id_user 
WHERE c.id_course='1';
The value of nickname is just "nickname", but I can not reference it 
to the teacher 2.

我做错了什么?我应该在 LEFT JOINS 中进行子查询吗?我对此有点迷茫。谢谢。

InoS Heo 的解决方案(在他的评论中有完整的解释)

我只需要添加这个:

GROUP_CONCAT(DISTINCT CONCAT(t.name_teacher, ':', IF(u.nickname_user IS NULL, 'NULL', u.nickname_user))) AS name_nick_map

所以我在 $row['name_nick_map'] 中有我想要的信息(老师 1:null,teacher 2:nickname2,teacher5:null)

【问题讨论】:

【参考方案1】:

这是您的架构和数据。 http://www.sqlfiddle.com/#!2/7af94/1 如果您在 sqlfiddle 中发布您的数据,我们将不胜感激。

我觉得要匹配老师的名字和昵称,你应该去掉GROUP_CONCAT()

就像这样:

SELECT name_course, t.name_teacher AS teachers,
                   u.nickname_user AS nickname 
FROM courses c
LEFT JOIN teachers t ON t.id_course_teacher=c.id_course
LEFT JOIN users u ON t.id_user_teacher=u.id_user 
WHERE c.id_course='c1';

+-------------+----------+-------------+
| name_course | teachers | nickname    |
+-------------+----------+-------------+
| c_name1     | t1_name  | u1_nickname |
| c_name1     | t2_name  | u2_nickname |
| c_name1     | t3_name  | NULL        |
+-------------+----------+-------------+

假设多对多关系,我猜你的数据库设计不是标准化的。

当教师和课程有多对多关系时,teacher_to_course 表是必需的。

courses_to_teachers(id_course, id_teacher)

SELECT name_course, t.name_teacher AS teachers,
               u.nickname_user AS nickname 
FROM courses c
LEFT JOIN course_to_teachers ct ON c.id_course = ct.id_course
LEFT JOIN teachers t ON t.id_teacher = ct.id_teacher
LEFT JOIN users u ON t.id_user_teacher=u.id_user 
WHERE c.id_course='c1';

更新

“我用php展示课程,所以可以创建一个数组array[t1_name=>u1_nickname, t2_name=>u2_nickname, etc...)?”

意思是,您正在使用GROUP_CONCAT() 来简化这样的数组?我认为没有GROUP_CONCAT()也可以制作。

无论如何,如果您需要GROUP_CONCAT() 为什么不试试这个? (你可以在这里测试http://www.sqlfiddle.com/#!2/7af94/24/0)

SELECT name_course, GROUP_CONCAT(CONCAT(t.name_teacher, ':', IF(u.nickname_user IS NULL, 'NULL', u.nickname_user))) AS name_nick_map
FROM courses c
LEFT JOIN teachers t ON t.id_course_teacher=c.id_course
LEFT JOIN users u ON t.id_user_teacher=u.id_user 
WHERE c.id_course='c1'
GROUP BY name_course;
+-------------+------------------------------------------------------+
| name_course | name_nick_map                                        |
+-------------+------------------------------------------------------+
| c_name1     | t1_name:u1_nickname,t2_name:u2_nickname,t3_name:NULL |
+-------------+------------------------------------------------------+

如您所见,"t3_name:NULL" 代表"t3_name has no nickname"

制作数组

我想知道你是不是在问这个代码。有以下查询和结果。

SELECT name_course, t.name_teacher AS teacher, u.nickname_user AS nickname 
FROM courses c
LEFT JOIN teachers t ON t.id_course_teacher=c.id_course
LEFT JOIN users u ON t.id_user_teacher=u.id_user 
WHERE c.id_course='c1';
+-------------+----------+-------------+
| name_course | teacher  | nickname    |
+-------------+----------+-------------+
| c_name1     | t1_name  | u1_nickname |
| c_name1     | t2_name  | u2_nickname |
| c_name1     | t3_name  | NULL        |
+-------------+----------+-------------+

制作数组。

$query = "SELECT ....";

$result = mysqli_query($query);

// error handling omitted

$CONTAINER = Array();
while ($row = mysqli_fetch_assoc($result))

    $CONTAINER[$row['teacher']] = $row['nickname']; 


print_r($CONTAINER);

mysqli_free_result($result);

可能print_r($CONTAINER) 会产生类似"array[t1_name=>u1_nickname, t2_name=>u2_nickname, etc...)" 的东西

【讨论】:

是的,我已经对数据库进行了规范化,我只是这样写它以使其更简单(我也使用许多其他表):) 问题是当我执行你的第二个查询时,我只获得一行:name_course (1) |教师 (t1_name,t2_name,t3_name) |昵称(NULL)。我用 php 展示课程,所以可以创建一个数组 $array[t1_name=>u1_nickname, t2_name=>u2_nickname, etc...); ?非常感谢您的宝贵时间。 http://www.sqlfiddle.com/#!2/6c743/2 在这里我得到 3 行,但在我的脚本中只有一个,但包含所有数据。否则,我将进行另一个查询以仅显示该信息,但我只是想知道我是否只能通过一个查询来做到这一点。 (大查询显示更多信息,有昵称的老师只是一小部分)。 太棒了……!!!我使用了您的第一个解决方案 GROUP_CONCAT(CONCAT(t.name_teacher....,但我添加了 DISTINCT: GROUP_CONCAT(DISTINCT CONCAT(t.name_teacher... 数组的第二个选项不是必需的;) 再次感谢..感谢您的宝贵时间。【参考方案2】:

您的查询中有一些错误,如果您正确执行,您会得到教师姓名的分组:

SELECT name_course,group_concat(DISTINCT t.name_teacher) AS teachers,
                   group_concat(DISTINCT u.nickname_user) AS nicknames
FROM courses c
LEFT JOIN teachers t ON t.id_course_teacher=c.id_course
LEFT JOIN users u ON t.id_user_teacher=u.id_user 
WHERE c.id_course='1';

【讨论】:

Gracias por la respuesta, pero fue un error mio al escribir :)

以上是关于MySQL 中可能存在或不存在的引用数据的主要内容,如果未能解决你的问题,请参考以下文章

带有熊猫数据框的内连接循环,用于可能存在或不存在的各种组合[重复]

如何使用mysql中存在或不存在的地方实现相交

在Python中删除可能存在或不存在的字典属性[重复]

在 c# 中,如何测试/获取/设置可能存在或不存在的注册表项?

我的查询需要啥,可能不存在或不存在? [复制]

编译器错误消息: CS0103: 当前上下文中不存在名称