查询设计,奇怪的结果 - SQL-Server的新功能

时间:2014-05-09 20:26:28

标签: sql sql-server-2008

我写了一个生成鬼记录的查询。以下是在一张桌子上产生正确结果的陈述连接到第二张桌子以抓住学生的LAST_ATTEND_DATE,注意LAST_ATTEND_DATE将不会显示,注释掉:

SELECT DISTINCT TOP 500
  SAC.STC_PERSON_ID AS CCID#,
  SAC.STC_COURSE_NAME AS CourseName,
  SAC.STC_TITLE AS Title,
  SAC.STC_VERIFIED_GRADE AS Grade,
  --CONVERT(varchar(10),SCS.SCS_LAST_ATTEND_DATE,101) AS LastAttended,
  SAC.STC_REPORTING_TERM AS Term,
  SAC.STC_ACAD_LEVEL AS AcadLevel
FROM STUDENT_ACAD_CRED SAC
JOIN STUDENT_COURSE_SEC SCS ON SAC.STC_PERSON_ID = SCS.SCS_STUDENT
WHERE (SAC.STC_ACAD_LEVEL = 'UG') AND (SCS.SCS_LAST_ATTEND_DATE IS NOT NULL)
ORDER BY SAC.STC_PERSON_ID;

这产生了我需要的东西,除了我需要在结果数据中显示学生最后参加日期。如果我取消上述语句的注释以显示LAST_ATTEND_DATE,则会显示4条记录,其中2条是重影记录。例如学生ID ='0000002',他在1992年秋天一次英语1010,做了一个D,然后在1993年秋季再次重新上课,并做了一个B.

 0000002  ENGL*1010   English I   D   92/FA   UG
 0000002  ENGL*1010   English I   B   93/FA   UG

如果LAST_ATTEND_DATE语句(CONVERT(varchar(10),SCS.SCS_LAST_ATTEND_DATE,101) AS LastAttended)未注释显示日期,则会显示3条额外的记录...

我尝试将两个表之间的查询从JOIN更改为LEFT JOIN,FULL JOIN和RIGHT JOIN。我总是得到另外3条不存在的记录。

 0000002   ENGL*1010   English I   B   01/19/1995   93/FA   UG
 0000002   ENGL*1010   English I   B   07/18/1996   93/FA   UG
 0000002   ENGL*1010   English I   B   09/25/1992   93/FA   UG
 0000002   ENGL*1010   English I   D   01/19/1995   92/FA   UG
 0000002   ENGL*1010   English I   D   07/18/1996   92/FA   UG

是否有人知道正确连接这两个表以正确显示数据的正确语法?

非常感谢您分享您的知识,

唐纳德,卡斯珀学院

2 个答案:

答案 0 :(得分:0)

很可能Student_Course_Sec表包含每个学生多条记录,而join语句未考虑这些记录。

例如,如果SCS表包含:

SCS_Student    SCS_CourseName    SCS_LastAttendDate
1              English           1/1/2014
1              Calculus          2/1/2014
2              English           3/1/2014
2              Philsolphy        4/1/2014

您的SAC表包含:

STC_PERSON_ID  STC_COURSE_NAME  etc.
1              English
1              Calculus
2              English
2              Philosophy

然后当你SELECT * FROM SAC JOIN SCS ON SAC.STS_PERSON_ID = SCS.SCS_STUDENT时,你的结果集如下所示:

(row) STC_ID STC_Course SCS_ID SCS_Course SCS_Date
1     1      English    1      English    1/1/2014
2     1      English    1      Calculus   2/1/2014
3     1      Calculus   1      English    1/1/2014
4     1      Calculus   1      Calculus   2/1/2014
5     2      English    2      English    3/1/2014
6     2      English    2      Philosophy 4/1/2014
7     2      Philosophy 2      English    3/1/2014
8     2      Philosophy 2      Philosophy 4/1/2014

您的WHERE子句会过滤掉STC_COURSE不是"英语"的所有行,而是留下4行(行号1,2,5,6)只有你真正想要的2(第1和第5行)。 (并且,因为您没有报告任何其他字段,它只是看起来像幻像记录"无处不在。)

要解决此问题,您需要在JOIN上添加其他条件,指定除ID之外的其他内容还需要匹配。在我的设计案例中,你需要说 JOIN STUDENT_COURSE_SEC SCS on SAC.STS_PERSON_ID = SCS.SCS_STUDENT and SAC.STC_COURSE_NAME = SCS.SCS_COURSE_NAME,只选择学生和课程都匹配的行。

答案 1 :(得分:0)

'ghost'记录实际上是真实的结果集。当您注释掉SCS.SCS_LAST_ATTEND_DATE时它们不显示的原因是您正在创建重复记录,因为日期是唯一的区分因素,并且您的DISTINCT正在抑制重复项。

如果您删除DISTINCT,并将SCS.SCS_LAST_ATTEND_DATE注释掉,那么您应该获得与取消注释日期时相同的行数。

使用JOIN类型意味着您并不真正知道要查询的内容。正如@MarkD在评论中所说,我们需要查看您的数据模型,以便进一步帮助您。