views:

669

answers:

4

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

A: 

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;
CheeseConQueso
That's a long way to do it. Where is the fullname coming from?
Jonathan Leffler
A: 

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.

MarkusQ
i dont even like my own explanation either... i just had to find all the id's who had stats of only ('FN%' or 'W%')
CheeseConQueso
A: 

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
Matt Hensley
where are you getting fullname and courses from?
CheeseConQueso
This produces more rows than required, and includes data that was not required, and references an undefined table...
Jonathan Leffler
It appears you are running Jenzabar CX - but I could be wrong. If you are, replace 'entity' with id_rec, and 'courses' with cw_rec.
Matt Hensley
No, you're right on.... thats creepy matt. I didn't want to use real id's and fullnames for obvious reasons.
CheeseConQueso
Your concat question was a dead giveaway. Email is in my profile if you have any CX specific questions.
Matt Hensley
oh from my other questions.... that makes sensethanks... i'll definately put it in my address book
CheeseConQueso
+3  A: 

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.

yukondude
Both queries work fine in Informix IDS 11.50.FC3W2 on Solaris 10.
Jonathan Leffler
yeah this works with my informix too
CheeseConQueso