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 |
+--------+------+----------+------+------+---------+---------+-------+------+
用示例说明我想要什么(如果您已经理解,则不需要)。
我想获取 JOHN
、SMITH
和 HELEN
的名称,因为它们在以下 [=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
子句过滤它。
我想比较不同行的一个属性,但前提是这些行具有另一个共同属性。
例子
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 |
+--------+------+----------+------+------+---------+---------+-------+------+
用示例说明我想要什么(如果您已经理解,则不需要)。
我想获取 JOHN
、SMITH
和 HELEN
的名称,因为它们在以下 [=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
子句过滤它。