select语句中带有子查询的重复行

时间:2020-10-13 15:04:53

标签: sql sql-server

我正在使用SQL Server学习数据库,而重复操作使我感到困惑:

SELECT t.tno, t.tname, classes = (SELECT COUNT(*) FROM teaching te WHERE te.tno = t.tno)
FROM teacher t, teaching t2
WHERE t.tno = t2.tno AND t2.Llanguage = 'English'

如果我使用上面的代码,则会得到包含许多重复行的结果,如下所示:

+------+----------+-------+
|tno   |tname     |classes|
+------+----------+-------+
|T01   |t1        |3      |
|T01   |t1        |3      |
|T03   |t3        |4      |
|T03   |t3        |4      |
|T03   |t3        |4      |
|T04   |t4        |3      |
|T05   |t5        |3      |
|T05   |t5        |3      |
+------+----------+-------+

但是,如果我不使用子查询,则不会发生重复。有人可以帮我吗?

更新10/14 teacherteaching中的数据:

teacher:
+------+----------+---+----------+--------------------+
|tno   |tname     |sex|birthday  |title               |
+------+----------+---+----------+--------------------+
|T01   |t1        |m  |1980-06-10|lecturer            |
|T02   |t2        |f  |1970-03-14|professor           |
|T03   |t3        |m  |1973-04-20|associate professor |
|T04   |t4        |m  |1981-08-30|lecturer            |
|T05   |t5        |f  |1975-07-20| associate professor|
|T06   |t6        |m  |1980-09-19|lecturer            |
+------+----------+---+----------+--------------------+
teaching:
+------+------+----------+----+
|tno   |cno   |Llanguage |Year|
+------+------+----------+----+
|T01   |801   |English   |2018|
|T01   |803   |Bilingual |2018|
|T01   |804   |English   |2018|
|T02   |801   |Bilingual |2018|
|T02   |804   |Bilingual |2018|
|T03   |802   |English   |2018|
|T03   |804   |Bilingual |2018|
|T03   |805   |English   |2018|
|T03   |806   |English   |2018|
|T04   |802   |Bilingual |2018|
|T04   |803   |English   |2018|
|T04   |805   |Bilingual |2018|
|T05   |801   |Bilingual |2018|
|T05   |802   |English   |2018|
|T05   |803   |English   |2018|
|T06   |803   |Bilingual |2018|
|T06   |806   |Bilingual |2018|
+------+------+----------+----+

对于加入样式,我的老师使用的幻灯片非常过时(也许是10年前?)。实际上,代码是几周前编写的,现在我已经习惯了使用inner join。但是,我仍然对这个问题感到困惑。

2 个答案:

答案 0 :(得分:1)

由于教师可以​​教多个英语课,因此您会得到重复。您会向每位老师展示他们的英语课的次数。

查询应做的事情(或我应做的假设):显示所有教至少一门英语课的老师及其整体班数。 “至少教一门英语课”的条件是可以在汇总教师行后检查的条件,因此可以将其放在HAVING子句中。

select t.tno, t.tname, count(t2.tno) as classes
from teacher t
inner join teaching t2 on t.tno = t2.tno
group by t.tno, t.tname
having count(case when t2.language = 'English' then 1 end) > 0

我不知道SQL Server是否实际上在t.tname子句中需要GROUP BY。标准SQL则没有,因为t.tno应该唯一地定义一位包括其姓名的教师。

正如其他人提到的那样:如果被教您使用逗号分隔的联接,那么最好退出您的课堂,教程或书本。

更新:您已经编辑了请求,但似乎仍然对联接的结果感到困惑。为了说明联接中发生了什么:

老师:

+------+----------+---+----------+--------------------+
|tno   |tname     |sex|birthday  |title               |
+------+----------+---+----------+--------------------+
|T01   |t1        |m  |1980-06-10|lecturer            |
|T02   |t2        |f  |1970-03-14|professor           |
+------+----------+---+----------+--------------------+

教学:

+------+------+----------+----+
|tno   |cno   |Llanguage |Year|
+------+------+----------+----+
|T01   |801   |English   |2018|
|T01   |803   |Bilingual |2018|
|T01   |804   |English   |2018|
|T02   |801   |Bilingual |2018|
|T02   |804   |Bilingual |2018|
+------+------+----------+----+

老师参加了英语课:

+------+----------+------+-----------+--------------------+-------+-------+-------------+--------+
|t.tno |t.tname   |t.sex |t.birthday |t.title             |t2.tno |t2.cno |t2.Llanguage |t2.Year |
+------+----------+------+-----------+--------------------+-------+-------+-------------+--------+
|T01   |t1        |m     |1980-06-10 |lecturer            |T01    |801    |English      |2018    |
|T01   |t1        |m     |1980-06-10 |lecturer            |T01    |804    |English      |2018    |
+------+----------+------+-----------+--------------------+-------+-------+-------------+--------+

其中将显示前两列以及tno的示教计数:

+------+----------+--------+
|t.tno |t.tname   |classes |
+------+----------+--------+
|T01   |t1        |3       |
|T01   |t1        |3       |
+------+----------+--------+

答案 1 :(得分:-1)

  1. 使用显式联接。 Left outerInner only。 除非您的表强制使用约束,否则请尽量不要使用inner joins
  2. 切勿在select语句中添加下标。在大型桌子上,您将使系统不堪重负。
  3. group by允许控制唯一行和聚合的定义。
SELECT t.tno, t.tname, classes =  COUNT(*)      
FROM teacher t
LEFT OUTER JOIN teaching t2 ON  t.tno = t2.tno    
WHERE t2.Llanguage = 'English'  AND t2.tno IS NOT NULL    
GROUP BY t.tno, t.tname