SQL:比较由另一个属性分组的两行相同属性

SQL: Compare two rows of same attribute grouped by another attribute

我想比较不同行的一个属性,但前提是这些行具有另一个共同属性。 例子 TableStudents

+------+---------+---------+-------+------+
| snum | sname   | major   | level | age  |
+------+---------+---------+-------+------+
|  101 | JOHN    | CS      | SR    |   19 |
|  102 | SMITH   | CS      | JR    |   20 |
|  103 | JACOB   | ECE     | SR    |   20 |
|  104 | TOM     | CS      | JR    |   20 |
|  105 | SID     | CS      | JR    |   20 |
|  106 | HARRY   | HISTORY | SR    |   21 |
|  107 | HELLEN  | CS      | JR    |   21 |
|  108 | BOB     | ENGLISH | SR    |   22 |
|  109 | ANDY    | ECE     | JR    |   21 |
|  110 | CHARLES | HISTORY | SR    |   23 |
+------+---------+---------+-------+------+

Table Class 其中 cname 是课程名称,fid 是教员 ID,你现在可以忽略它,因为我没有包括那个 table 因为这里不需要。

+--------+----------+------+------+
| cname  | meets_at | room | fid  |
+--------+----------+------+------+
| CSC342 | Morning  | R128 |  201 |
| CSC343 | Noon     | R128 |  203 |
| CSC345 | Night    | R154 |  204 |
| ECE300 | Morning  | R111 |  202 |
| ECE301 | Noon     | R111 |  203 |
| ENG366 | Morning  | R154 |  203 |
| ENG367 | Evening  | R111 |  205 |
| HIS320 | Evening  | R128 |  205 |
+--------+----------+------+------+

Table Enrolled - 在以上两个 table 之间连接 link 并告诉哪个学生在哪个课程中。

+------+--------+
| snum | cname  |
+------+--------+
|  101 | CSC342 |
|  101 | CSC343 |
|  101 | CSC345 |
|  101 | ECE300 |
|  101 | ENG366 |
|  102 | CSC343 |
|  102 | CSC345 |
|  102 | ECE301 |
|  103 | ECE300 |
|  103 | ECE301 |
|  104 | CSC342 |
|  104 | ECE301 |
|  105 | CSC345 |
|  105 | ECE300 |
|  106 | ENG366 |
|  106 | HIS320 |
|  107 | CSC342 |
|  107 | ENG366 |
|  108 | ENG367 |
|  108 | HIS320 |
|  109 | ECE300 |
|  109 | ECE301 |
|  110 | ENG366 |
|  110 | HIS320 |
+------+--------+

我想找到所有在课程时间上有冲突的学生的名字 (meets_at)。

我已经尝试了以下(这肯定不是解决方案,因为我不确定应该尝试什么)。

SELECT * FROM Student 
NATURAL JOIN Class C1 
NATURAL JOIN Class C2 
NATURAL JOIN Enrolled 
WHERE C1.meets_at = C2.meets_at 
GROUP BY snum;

我选择了 *,因为如果我对回复感到满意,我会将其更改为 sname。我想以某种方式比较不同 cname(课程名称)的同一学生的 meets_at 属性,这就是我尝试对它们进行分组的原因。上述查询的响应(显然你已经可以预料但只是为了节省你的精力。)

+--------+------+----------+------+------+---------+---------+-------+------+
| cname  | snum | meets_at | room | fid  | sname   | major   | level | age  |
+--------+------+----------+------+------+---------+---------+-------+------+
| CSC342 |  101 | Morning  | R128 |  201 | JOHN    | CS      | SR    |   19 |
| CSC343 |  102 | Noon     | R128 |  203 | Smith   | CS      | JR    |   20 |
| ECE300 |  103 | Morning  | R111 |  202 | JACOB   | ECE     | SR    |   20 |
| CSC342 |  104 | Morning  | R128 |  201 | TOM     | CS      | JR    |   20 |
| CSC345 |  105 | Night    | R154 |  204 | SID     | CS      | JR    |   20 |
| ENG366 |  106 | Morning  | R154 |  203 | HARRY   | HISTORY | SR    |   21 |
| CSC342 |  107 | Morning  | R128 |  201 | HELLEN  | CS      | JR    |   21 |
| ENG367 |  108 | Evening  | R111 |  205 | BOB     | ENGLISH | SR    |   22 |
| ECE300 |  109 | Morning  | R111 |  202 | ANDY    | ECE     | JR    |   21 |
| ENG366 |  110 | Morning  | R154 |  203 | CHARLES | HISTORY | SR    |   23 |
+--------+------+----------+------+------+---------+---------+-------+------+

用示例说明我想要什么(如果您已经理解,则不需要)。 我想获取 JOHNSMITHHELEN 的名称,因为它们在以下 [=49= 中有多个具有相同 meets_at 属性的 cname ](通过连接所有 tables 制成)。

+--------+------+----------+------+------+---------+---------+-------+------+
| cname  | snum | meets_at | room | fid  | sname   | major   | level | age  |
+--------+------+----------+------+------+---------+---------+-------+------+
| CSC342 |  101 | Morning  | R128 |  201 | JOHN    | CS      | SR    |   19 |
| CSC343 |  101 | Noon     | R128 |  203 | JOHN    | CS      | SR    |   19 |
| CSC345 |  101 | Night    | R154 |  204 | JOHN    | CS      | SR    |   19 |
| ECE300 |  101 | Morning  | R111 |  202 | JOHN    | CS      | SR    |   19 |
| ENG366 |  101 | Morning  | R154 |  203 | JOHN    | CS      | SR    |   19 |
| CSC343 |  102 | Noon     | R128 |  203 | Smith   | CS      | JR    |   20 |
| CSC345 |  102 | Night    | R154 |  204 | Smith   | CS      | JR    |   20 |
| ECE301 |  102 | Noon     | R111 |  203 | Smith   | CS      | JR    |   20 |
| ECE300 |  103 | Morning  | R111 |  202 | JACOB   | ECE     | SR    |   20 |
| ECE301 |  103 | Noon     | R111 |  203 | JACOB   | ECE     | SR    |   20 |
| CSC342 |  104 | Morning  | R128 |  201 | TOM     | CS      | JR    |   20 |
| ECE301 |  104 | Noon     | R111 |  203 | TOM     | CS      | JR    |   20 |
| CSC345 |  105 | Night    | R154 |  204 | SID     | CS      | JR    |   20 |
| ECE300 |  105 | Morning  | R111 |  202 | SID     | CS      | JR    |   20 |
| ENG366 |  106 | Morning  | R154 |  203 | HARRY   | HISTORY | SR    |   21 |
| HIS320 |  106 | Evening  | R128 |  205 | HARRY   | HISTORY | SR    |   21 |
| CSC342 |  107 | Morning  | R128 |  201 | HELLEN  | CS      | JR    |   21 |
| ENG366 |  107 | Morning  | R154 |  203 | HELLEN  | CS      | JR    |   21 |
| ENG367 |  108 | Evening  | R111 |  205 | BOB     | ENGLISH | SR    |   22 |
| HIS320 |  108 | Evening  | R128 |  205 | BOB     | ENGLISH | SR    |   22 |
| ECE300 |  109 | Morning  | R111 |  202 | ANDY    | ECE     | JR    |   21 |
| ECE301 |  109 | Noon     | R111 |  203 | ANDY    | ECE     | JR    |   21 |
| ENG366 |  110 | Morning  | R154 |  203 | CHARLES | HISTORY | SR    |   23 |
| HIS320 |  110 | Evening  | R128 |  205 | CHARLES | HISTORY | SR    |   23 |
+--------+------+----------+------+------+---------+---------+-------+------+
24 rows in set (0.001 sec)


你要做的是按学生和 'meets at' 属性 分组,然后简单地计算每个组合有多少条记录。

如果有多个记录与 JOHN, Morning 关联,那么这表明存在冲突,因此您正在寻找计数大于 1 的情况:

      SELECT snum, sname, meets_at, COUNT(*) > 1 AS has_clash
        FROM Student
NATURAL JOIN Enrolled
NATURAL JOIN Class
    GROUP BY snum, sname, meets_at

请注意我是如何按 snum(学生独有)分组的,但也必须按 sname 分组,因为这是您要报告的内容(名称可能不是唯一的)一个学生,所以按 snum 分组仍然是必要的)。

这将 return 一个 table 的学生 ID 和姓名,他们在 类 见面的时间,以及一个布尔值列,指示他们当时是否有冲突.

如果您只想查看那些有冲突的学生,您可以在 GROUP BY 之后使用 HAVING COUNT(*) > 1 子句过滤它。