【问题标题】:Detecting relationships among MySQL DB records检测 MySQL 数据库记录之间的关系
【发布时间】:2013-12-10 09:28:15
【问题描述】:

假设我有 3 个数据库表:

  1. 教师,具有以下字段:
    • 身份证
    • 姓名
  2. 主题,具有以下字段:
    • 身份证
    • 姓名
  3. teachers-subjects,具有以下字段:
    • teacher_id
    • subject_id

所以,一些老师有共同的学科。

我考虑过查询的算法

对于subjects表中的每条记录:

选择 Teachers_subjects 表中的计数。
如果计数大于 1
在teacher_subjects中,获取subject_id为s的teacher_id's。

建立关系对。

我想得到如下输出:

+----------+----------+---------------+
| Teacher1 | Teacher2 | Relationships |
+----------+----------+---------------+
| John     | Larry    |            10 |
| John     | Samantha |            12 |
| Samantha | Larry    |             9 |
| Ian      | Louis    |             3 |
+----------+----------+---------------+

如果我需要检索哪些主题建立了关系,我们需要得到类似的东西:

+----+----------+----------+
| id | teacher1 | teacher2 |
+----+----------+----------+
|  1 | John     | Larry    |
|  2 | John     | Samantha |
|  3 | Samantha | Larry    |
|  4 | Ian      | Louis    |
+----+----------+----------+

还有类似的:

+-----+------------+
| id  |  subject   |
+-----+------------+
| 1   | math       |
| 1   | english    |
| 1   | science    |
| ... | ...        |
| ... | ...        |
| 4   | science    |
| 4   | literature |
| 4   | databases  |
+-----+------------+

以图形方式,我在通过网络浏览器查阅的图表中表示这一点:

所以当我悬停在一条边上时,它会显示关系信息。

我将通过 php 编程接收查询结果,这样的查询或存储过程会为我产生这样需要的输出吗?

【问题讨论】:

  • 你能再解释一下最后一张桌子吗?
  • 在第二张表中,我得到了有关系的教师(共同学科)和关系的数量,每条记录都有一个 ID。所以在最后一张表中,我得到了哪些是关系,老师们有哪些共同点。

标签: php mysql mysqli


【解决方案1】:

试试这个(你应该在 SQLFiddle 中加载一些示例数据以便更好地测试)

SELECT t1.`name` AS teacher1, t2.`name` AS teacher2, count(*)
FROM teachers AS t1
JOIN teachers AS t2
  ON t1.id > t2.id
JOIN teacher_subjects AS ts1
  ON ts1.teacher_id = t1.id
JOIN teacher_subjects AS ts2
  ON ts2.teacher_id = t2.id
    AND ts2.subject_id = ts1.subject_id
GROUP BY teacher1, teacher2
ORDER BY COUNT(*) DESC;

【讨论】:

  • 我喜欢它,我不知道如何摆脱那些重复的记录,但你的 ON t1.id > t2.id 做到了:)
  • 谢谢!我去看看!
  • @KeluThatsall - 谢谢,我们的解决方案非常接近表别名。 > 是其他人的解决方案,而我有 <> 像你一样解决问题:)
【解决方案2】:

这些是我对 SQL 的建议。

请记住,这些解决方案中的每一个都只是对以前的解决方案进行了一些修改。

第一张桌子

http://sqlfiddle.com/#!2/dc3f2/3

SELECT t1.name as 'Teacher1', t2.name as 'Teacher2', count(*) AS 'Relationships' 
FROM teachers t1 
JOIN teachers t2 ON t1.id > t2.id
JOIN teachers_subjects ts1 ON ts1.teacher_id = t1.id
JOIN teachers_subjects ts2 ON ts2.teacher_id = t2.id AND ts1.subject_id = ts2.subject_id
GROUP BY ts1.teacher_id, ts2.teacher_id;

第二张表

我认为它现在可以工作了。

http://sqlfiddle.com/#!2/dc3f2/22

SELECT @rownum := @rownum + 1 as id, relations.Teacher1, relations.Teacher2
FROM (SELECT t1.name as 'Teacher1', t2.name as 'Teacher2'
FROM teachers t1 
JOIN teachers t2 ON t1.id > t2.id
JOIN teachers_subjects ts1 ON ts1.teacher_id = t1.id
JOIN teachers_subjects ts2 ON ts2.teacher_id = t2.id AND ts1.subject_id = ts2.subject_id
GROUP BY ts1.teacher_id, ts2.teacher_id) as relations,
(SELECT @rownum := 0) r;

第三张表

http://sqlfiddle.com/#!2/dc3f2/27

SELECT id, subject
FROM
(SELECT @rownum := @rownum + 1 as id, relations.Teacher1, relations.Teacher2, relations.id1, relations.id2
FROM (SELECT t1.name as 'Teacher1', t2.name as 'Teacher2', t1.id as 'id1', t2.id as 'id2'
FROM teachers t1 
JOIN teachers t2 ON t1.id > t2.id
JOIN teachers_subjects ts1 ON ts1.teacher_id = t1.id
JOIN teachers_subjects ts2 ON ts2.teacher_id = t2.id AND ts1.subject_id = ts2.subject_id
GROUP BY ts1.teacher_id, ts2.teacher_id) as relations,
(SELECT @rownum := 0) r) as rel
JOIN
(SELECT t1.id as 'id1', t2.id as 'id2', s.name as 'subject'
FROM teachers t1 
JOIN teachers t2 ON t1.id > t2.id
JOIN teachers_subjects ts1 ON ts1.teacher_id = t1.id
JOIN teachers_subjects ts2 ON ts2.teacher_id = t2.id AND ts1.subject_id = ts2.subject_id
JOIN subjects s ON ts1.subject_id = s.id) as rel_subjects
ON rel.id1 = rel_subjects.id1 AND rel.id2 = rel_subjects.id2
ORDER BY id

最后一件事。请记住,那些用于关系的伪键是非常多变的。这意味着如果您添加新行并删除一些行,您将更改这些关系的 ID。因此,为了避免出现任何错误,您不能在数据库中的任何存储列中使用它们 - 只需在 SELECT 查询中使用它们。

【讨论】:

  • 谢谢,我正在检查。
  • 愚蠢的问题,但我宁愿问,查询中的@ 是什么?
  • 用于变量。在这里,它只是用作为这些行生成伪键的技巧。 stackoverflow.com/questions/1971826/…
  • 谢谢!我认为将 ID 分配给关系并生成表示关系 ID 和主题的 nn 表更实用。我真的很感谢你的帮助
  • 等等,我认为这是第二个表,但它在关系字段下显示了主题 ID,对吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
  • 1970-01-01
  • 2021-06-13
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多