简体   繁体   中英

Perform right outer join with a condition for left table

I have two tables,

Student:

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

Attendance:

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

My required output is:

Some query with where condition as "where date between '10-09-2013' and '13-10-2013' "

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

I tried using:

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

And the Output is:

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

I want the remaining values from the student table to also be appended. I have tried many different queries, but all have been unsuccessful. Is there a query that will return the required output above?

You need to move the criteria from the where to the join:

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;

At the moment even though you have an outer join, by referring to the outer table in the where clause you effectively turn it into an inner join. Where there is no match in attendance , s.Date will be NULL , and because NULL is not between '10-09-2013' and '13-10-2013' the rows are excluded.

It is not apparent from the question, but I would image that what you are actually looking for is this. It appears you are just after a count of entries in attendance where status = 'A' by student:

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;

I have removed s.statuss from the group by, and changed the count so that there is only one row per student, rather than one row per status per student. I have changed the column within the count to a column in the attendance status table, to ensure that you get a count of 0 when there are no entries in attendance. if you use a column in students you will get a count of 1 even when there are no entries. Finally, since you are only interested in entries with statuss = 'A' I have also moved this to the join condition.

On one final note, it is advisable when using strings for dates to use the culture insensitive format yyyyMMdd , as this is completely unanbiguous, 20130201' is always the 1st February, and never 2nd January, whereas in your query 10-09-2013' could be 10th September, or 9th October, depending on your settings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM