如何获取mysql中两个表中列之间的匹配数
Posted
技术标签:
【中文标题】如何获取mysql中两个表中列之间的匹配数【英文标题】:how to get the count of matches between columns in two tables in mysql 【发布时间】:2012-10-04 05:55:00 【问题描述】:我正在尝试弄清楚如何在 mysql 中处理这种情况 -
一共有三个表 - t_student, t_teacher, t_result
表格的结构(基本上每个表格中的列)如下:
t_student:
s_id, s_name, s1, s2, s3
其中 s_id 是主键,s_name 是学生姓名,(s1,s2,s3) 是数学、物理、化学等科目。
t_teacher:
t_id, t_name, s1, s2, s3
其中 t_id 是主键,t_name 是教师姓名,(s1,s2,s3) 是数学、物理、化学等科目。
t_result:
r_id, s_name, t_name, count
其中 r_id 是主键,s_name 是学生姓名(来自学生表),t_name 是教师姓名(来自教师表),count 给出计数(稍后会详细介绍)
>现在,我想做的如下:
学生和教师表中可能有任意数量的记录,但目前在结果表中没有。现在,我想使用 mySQL 扫描学生表的内容,并且对于该表中的每条记录,我想提取:
s1 然后将值与教师表中的 (s1,s2,s3) 列进行比较 s2,然后将值与教师表中的 (s1,s2,s3) 列进行比较 s3,然后将值与教师表中的 (s1,s2,s3) 列进行比较
并获取匹配值的数量并存储在count中。
为了更清楚,如果student表的第一条记录s1、s2和s3是“phy”、“chem”和“maths”,如果teacher表的第一条记录是“maths”、“phy” , "computer", 那么在这种情况下,student.s1 与teacher.s2 匹配-所以现在count 为1。然后student.s2 与teacher 表中的s1,s2,s3 匹配,但匹配为0,所以count 为保留1个;再次 student.s3 与教师表中的 s1,s2,s3 匹配,这次它与teacher.s1 匹配,因此计数增加到 2。 因此,在比较学生表中的第一条记录与教师表的第一条记录时,我得到 count=2。现在我将在结果表中插入一行,包含学生姓名、教师姓名以及如此获得的计数。
基本上我想获取学生表和教师表之间的s1,s2,s3匹配数,对于学生表中的每一行,然后将其放入结果表中。
我只知道 mysql 中的基本操作——比如选择插入删除等。我假设这样的操作需要更多,比如 plsql 和存储过程?
仅供参考,我正在使用 phpmyadmin,表格存储在那里。我将使用 php 从表中获取结果,并执行这些查询。
请告诉我这个方法。
谢谢!
【问题讨论】:
【参考方案1】:实际上,您不需要任何程序代码来解决此问题。该方法称为 “正常化”。您需要多个表来表示教师的科目,以便 s1、s2、s3 值转到单独表中的单个列,该表与教师表具有外键关系。其他关系也一样。 (这就是为什么首先使用术语“关系数据库”。)
相关讨论在这里:DB Design: 1st Normal Form and Repeating Groups。
编辑
看起来像是作业而不是生产问题:)。无论如何,您仍然可以尝试使用复杂的纯 SQL 方法在 查询 中而不是在模式中进行规范化。奇怪但并非不可能。
这就是诀窍的精髓。使用它作为子查询来获得数据的规范化表示:
select s_id, s_name, s1 s from t_student
union
select s_id, s_name, s2 s from t_student
union
select s_id, s_name, s3 s from t_student
【讨论】:
感谢您对此进行调查,但我想您误解了我的要求。两个表中的记录是不同的,并且来自不同的来源(在高层次上),并且并不真正依赖。所以第三个表 - 结果表确实是必需的。可能我没有完全解释事情,但相信我这不是关于标准化。我只是想知道如何通过将每个学生(s1,s2,s3)与老师(s1,s2,s3)匹配来确定计数。再次感谢。 很有可能,我们都没有抓住重点。但看起来这里的所有答案基本上都差不多:消除重复的 s1、s2、s3 组,并改用一对多关系。确实是标准化。 是的..我想我的问题还不够清楚!我想我需要编写程序,然后获取匹配计数,然后输入结果表。现在正在研究这种方法。无论如何,谢谢你的帮助:) 添加了另一个答案,其中包含在内部规范化您的数据的查询。【参考方案2】:您的数据库设计需要一些工作。首先标准化您的数据,将重复的主题列从教师和学生表中移出。您可以通过创建以下表格来做到这一点:
CREATE TABLE t_subjects ( subject_id INT, name VARCHAR(30) );
CREATE TABLE t_teacher_subjects ( teach_id INT, subject_id INT);
CREATE TABLE t_student_subjects ( student_id INT, subject_id INT);
从教师和学生中删除 s1、s2、s3 列,然后您将能够在单个查询中填充结果表(假设它具有 auto_increment 主键) - 如下所示:
insert into t_result (s_name, t_name, count)
select t_teacher.t_name, t_student.s_name, count(*) as c from
t_teacher_subjects
inner join t_student_subjects on t_teacher_subjects.subject_id = t_student_subjects.subject_id
inner join t_teacher on t_teacher_subjects.teach_id = t_teacher.t_id
inner join t_student on t_student_subjects.student_id = t_student.s_id
group by t_teacher.t_name, t_student.s_name;
【讨论】:
谢谢,但我还是无法将主题从其他表格中移出。事实上,学生表科目和教师表科目是完全不同的,它们之间并没有关联。这两个表是独立的。我的要求是匹配主题以查看它是否存在于教师表的任何列中,并获取 Count 中匹配主题的数量。我想我让我的原始帖子有点混乱,但是这些表格无法进一步规范化。有什么方法可以在不归一化的情况下获得计数?【参考方案3】:您应该将表格修改为
t_student:
s_id, s_name, s_s
和
t_teacher:
t_id, t_name, t_s
并将您的 s1、s2、s3 拆分为单独的行。然后你可以在 t_student 和 t_teacher 之间做一个简单的连接。
【讨论】:
【参考方案4】:嗯。感谢您的挑战。一个很好的心理锻炼:)。
这是查询;只需将其转换为插入:
select s_name, t_name, count(*) cnt from
(
select s.s_name, s.s s_s, t.t_name, t.s t_s from
(
select s_id, s_name, s1 s from t_student
union
select s_id, s_name, s2 s from t_student
union
select s_id, s_name, s3 s from t_student
) s
inner join
(
select t_id, t_name, s1 s from t_teacher
union
select t_id, t_name, s2 s from t_teacher
union
select t_id, t_name, s3 s from t_teacher
) t
on t.s = s.s
) m
group by s_name, t_name
;
编辑:实际运行:
mysql> select * from t_student;
+------+--------+------+------+------+
| s_id | s_name | s1 | s2 | s3 |
+------+--------+------+------+------+
| 1 | st1 | qqq | www | eee |
| 2 | st2 | 111 | 222 | 333 |
| 3 | st3 | zzz | xxx | ccc |
+------+--------+------+------+------+
3 rows in set (0.00 sec)
mysql> select * from t_teacher;
+------+--------+------+------+------+
| t_id | t_name | s1 | s2 | s3 |
+------+--------+------+------+------+
| 1 | te1 | qqq | www | eee |
| 2 | te2 | 111 | 222 | nnn |
| 3 | te3 | zzz | nnn | nnn |
+------+--------+------+------+------+
3 rows in set (0.00 sec)
mysql> select s_name, t_name, count(*) cnt from
-> (
-> select s.s_name, s.s s_s, t.t_name, t.s t_s from
-> (
-> select s_id, s_name, s1 s from t_student
-> union
-> select s_id, s_name, s2 s from t_student
-> union
-> select s_id, s_name, s3 s from t_student
-> ) s
-> inner join
-> (
-> select t_id, t_name, s1 s from t_teacher
-> union
-> select t_id, t_name, s2 s from t_teacher
-> union
-> select t_id, t_name, s3 s from t_teacher
-> ) t
-> on t.s = s.s
-> ) m
-> group by s_name, t_name
-> ;
+--------+--------+-----+
| s_name | t_name | cnt |
+--------+--------+-----+
| st1 | te1 | 3 |
| st2 | te2 | 2 |
| st3 | te3 | 1 |
+--------+--------+-----+
3 rows in set (0.00 sec)
【讨论】:
hmm.. 干得好,但仍然没有一个答案是我想要的。 :) 为了更清楚,如果student表的第一条记录s1、s2和s3分别是“phy”、“chem”和“maths”,如果teacher表的第一条记录是“maths” ", "phy", "computer",那么在这种情况下,student.s1 与teacher.s2 匹配-所以现在计数为1。然后student.s2 与teacher 表中的s1,s2,s3 匹配,但匹配是0,所以count保持为1;再次 student.s3 与教师表中的 s1,s2,s3 匹配,这次匹配到了 teacher.s1,所以 count 增加到 2。 所以在比较学生表中的第一条记录与教师表的第一条记录时,我得到 count=2。现在我将在结果表中插入一行,包含学生姓名、教师姓名以及如此获得的计数。 full.stack.ex 的答案将给出您描述的结果。通过旋转每个学生和教师表中的所有学科列,您可以获得标准化数据的副本,一个学生可以多次匹配教师,这将产生您正在寻找的结果。 我实际上已经用 MySQL 试过了。你?我已经用测试数据和结果编辑了答案。和你想要的有什么不同?以上是关于如何获取mysql中两个表中列之间的匹配数的主要内容,如果未能解决你的问题,请参考以下文章
我如何在 MYSQL 表中找到两个不同日期之间的数据,例如(29-05-2021 到 08-06-2021)