Question

I'm trying to build a SQL query that will count both the total number of rows for each id, and the number of 'FN%' and 'W%' grades grouped by id. If those numbers are equal, then the student only has either all 'FN%' or all 'W%' or a combination of both.

I need a list of all the id's who only have stats of 'FN%' or 'W%'

example id # 683 & 657 would make it into the result set of the query, but 603, 781 & 694 would not

   id stat
  683 WF
  683 WF
  683 WF
  683 WF
  683 W
  683 W
  657 W
  657 W
  657 W
  657 W
  781 B+
  781 IP
  781 WP
  781 WP
  603 FN
  603 FN
  603 F
  603 FN
  603 FN
  694 B
  694 B+
  694 CI
  694 LAB
  694 WF
  694 WF

sample output:

683
657

Was it helpful?

Solution

Here are two possible solutions that I can think of. I'm not sure if they'll work in Informix:

SELECT  id
FROM    foo a
GROUP   BY id
HAVING  COUNT(*) = (
                SELECT  COUNT(*)
                FROM    foo b
                WHERE   a.id = b.id
                AND     (b.stat LIKE 'FN%' OR b.stat LIKE 'W%')
        );

And if subqueries in the HAVING clause are verboten, maybe this will work instead:

SELECT  id
FROM    (
                SELECT  id, COUNT(*) stat_count
                FROM    foo
                WHERE   (stat LIKE 'FN%' OR stat LIKE 'W%')
                GROUP   BY id
        ) a
WHERE   stat_count = (SELECT COUNT(*) FROM foo b WHERE a.id = b.id);

Update: I just tried these in Oracle, and both work.

OTHER TIPS

That explanation makes my head hurt. Are you looking for the union of these two sets?

  • ids which only have stats matching "W%"
  • ids which only have stats matching "FN%"

If that's the case, make it a UNION query with a sub-query for each of the sets.

Where xxxx is the temp table that holds this info to be processed.....

select id, fullname, count(id) ttl 
from xxxx 
group by id, fullname 
into temp www with no log;


select id, fullname, count(id) ttl_f 
from xxxx 
where grd like 'FN%' or grd like 'W%' 
group by id, fullname 
into temp wwww with no log;


select www.id, www.fullname 
from www, wwww 
where www.id = wwww.id and www.ttl = wwww.ttl_f;

This was written against the original question:

select first 50
c.id,
(select trim(fullname) from entity where id = c.id) fullname,
count(*),
(select count(*) from courses where id = c.id and grd like 'FN%') FN,
(select count(*) from courses where id = c.id and grd like 'W%') W
from courses c
group by 1

The subquery to retrieve the name is much faster than using a join for some reason.

Edit: The following will have the same behavior as yukondude's answer but performs better on our HPUX / Informix v10.00.HC5 box.

select c.id
from courses c
where not exists (
        select id
        from courses
        where (grd not like 'W%' and grd not like 'FN%')
        and id = c.id
)
group by 1
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top