使用左表的条件执行右外连接

时间:2013-09-30 15:40:04

标签: sql sql-server sql-server-2008

我有两张桌子,

学生:

rollno  | name 
1       | Abc
2       | efg
3       | hij
4       | klm

出勤:

name | date       |status
Abc  | 10-10-2013 | A
efg  | 10-10-2013 | A
Abc  | 11-10-2013 | A
hij  | 25-10-2013 | A

我要求的输出是:

某些查询条件为“在'10 -09-2013'和'13 -10-2013之间的日期'”

rollno| name |count
1     | Abc  | 2
2     | efg  | 1
3     | hij  | 0
4     | klm  | 0

我尝试使用:

SELECT p.rollno,p.name,case when s.statuss='A' then COUNT(p.rollno) else '0' end as count 
from    attendance s 
        right outer join student p 
            on s.rollno=p.rollno 
where   s.date between '10-09-2013' and '13-10-2013' 
group by p.rollno,p.regno,p.name,s.statuss 
order by p.rollno

输出是:

rollno| name |count
1   | Abc  | 2
2   | efg  | 1

我希望还附加student表中的剩余值。我尝试了很多不同的查询,但都没有成功。是否有一个查询将返回上面的所需输出?

1 个答案:

答案 0 :(得分:2)

您需要将条件从联接的位置移动:

SELECT p.rollno,p.name,case when s.statuss='A' then COUNT(p.rollno) else 0 end as count 
from    attendance s 
        right outer join student p 
            on s.rollno=p.rollno 
            and s.date between '10-09-2013' and '13-10-2013' 
group by p.rollno,p.regno,p.name,s.statuss 
order by p.rollno;

目前,即使你有一个外部联接,通过引用where子句中的外部表,你可以有效地将它转换为内部联接。如果attendance中没有匹配项,则s.Date将为NULL,并且因为NULL不在'10-09-2013' and '13-10-2013'之间,所以排除了这些行。

这个问题并不明显,但我会想到你实际上正在寻找的是这个。看来你刚刚参加了一个参赛人数,其中状态=' A'由学生:

SELECT  p.rollno,
        p.name,
        COUNT(s.statuss) as count 
from    attendance s 
        right outer join student p 
            on s.rollno=p.rollno 
            and s.date between '10-09-2013' and '13-10-2013' 
            AND s.statuss = 'A'
group by p.rollno,p.regno,p.name,
order by p.rollno;

我已从组中删除了s.statuss,并更改了计数,以便每个学生只有一行,而不是每个学生每个状态一行。我已将计数中的列更改为出勤状态表中的列,以确保在没有出席条目时计数为0。如果您在学生中使用专栏,即使没有参赛作品,您也会获得1分。最后,由于您只对statuss = 'A'条目感兴趣,我还将其移至连接条件。

最后一点,建议使用日期字符串来使用不区分大小写的格式yyyyMMdd,因为这完全是不明确的,20130201' is always the 1st February, and never 2nd January, whereas in your query 10-09-2013'可能是9月10日或10月9日,具体取决于您的设置。