count () comparações Informix SQL
Pergunta
Eu estou tentando construir uma consulta SQL que contará tanto o número total de linhas para cada id, eo número de 'FN%' e 'W%' classes agrupadas por id. Se esses números são iguais, então o aluno tem apenas quer tudo 'FN%' ou todos '% W' ou uma combinação de ambos.
Eu preciso de uma lista de todos os IDs que só têm estatísticas de 'FN%' ou 'W%'
exemplo id # 683 & 657 iria fazê-lo no conjunto de resultados da consulta, mas 603, 781 e 694 não seria
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
saída da amostra:
683
657
Solução
Aqui estão duas soluções possíveis que eu posso pensar. Eu não tenho certeza se eles vão trabalhar em 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%')
);
E se subconsultas na cláusula HAVING
são verboten, talvez isso vai funcionar em vez disso:
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:. Eu apenas tentei estes em Oracle, e ambos trabalham
Outras dicas
Essa explicação faz minha cabeça doer. Você está procurando a união destes dois conjuntos?
- ids que só tem estatísticas correspondentes "W%"
- ids que só tem estatísticas correspondentes "FN%"
Se for esse o caso, torná-lo uma consulta de união com uma sub-consulta para cada um dos conjuntos.
Onde xxxx é a tabela temporária que contém esta informação a ser processada .....
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;
Isto foi escrito contra a pergunta original:
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
A subconsulta para recuperar o nome é muito mais rápido do que usar uma junção por algum motivo.
Edit: A seguir irá ter o mesmo comportamento como a resposta da yukondude mas executa melhor na nossa caixa de HPUX / Informix v10.00.HC5.
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