Dúvida SQL URGENTE [RESOLVIDO]

15 respostas
M

Pessoal, Boa Tarde,
estou com problemas em uma consulta sql, segue a consulta:

select m.idcontato from mensalidade m inner join contato c where c.situacao ='Ativo' and m.idcontato not in(select m.idcontato from mensalidade m where m.mes= 'JANEIRO' and m.pago ='1' or m.pago = '0') group by m.idcontato

o problema é o seguinte, deveria retornar o idcontato 15 pois nao tem o mes de janeiro pago, nem esta devedor, m.pago='1 seria pago m.mapo=‘0’ seria nao pago, porem o problema é que nao retorna nenhum valor e deveria retornar idcontato=15 o estranho é que a consulta funcionava e parou de funcionar, se eu separar a consulta:

select m.idcontato from mensalidade m inner join contato c where c.situacao ='Ativo'

retorna o valor m.idcontato=15
e

select m.idcontato from mensalidade m where m.mes= 'JANEIRO' and m.pago ='1' or m.pago = '0'

tambem retorna o valor 15 é oq eu preciso, porque a consulta junta nao funciona?? preciso de ajuda dos mais experientes.

abraços a todos

15 Respostas

neno

eu acho que essa query ficou mei ocontraditória.

se o primerio sql retorna 15, e o segundo retorna 15

o fato de vc fazer a primeira consulta e a segunda com um “NOT IN” quer dizer,… “faz a primeira consulta, mas não traga o resultado da segunda consulta”, entende? uma consulta ta anulando a outra…

E

é simples, vamos pegar essa consulta em passos:

select m.idcontato from mensalidade m where m.mes= 'JANEIRO' and m.pago ='1' or m.pago = '0' retorna 15

select m.idcontato from mensalidade m inner join contato c where c.situacao = 'Ativo' and m.idcontato not in(15) group by m.idcontato

por ter um m.id_contato not in (15), nunca retornaria 15.

uma sugestão, ao invés de usar subconsulta para verificar um not in no where, faça assim (fica mais rápido)

select m.idcontato from mensalidade m inner join contato c left join ( select m.idcontato from mensalidade m where m.mes= 'JANEIRO' and m.pago ='1' or m.pago = '0' ) s on m.id_contato = s.id_contato where c.situacao = 'Ativo' and s.idcontato is null group by m.idcontato

M

a intencao dessa sql é para, retornar o idcontato que nao pagou ou nao esta cadastrado como nao pago na tabela mensalidade, assim eu gero a mensalidade do mes de janeiro para quem ainda nao esta cadastrado como inadimplente ou quem ja pagou

select
m.idcontato
from mensalidade m
inner join contato c
left join (
select m.idcontato
from mensalidade m
where m.mes= ‘JANEIRO’
and m.pago =‘1’
or m.pago = ‘0’
) s
on m.idcontato = s.idcontato
where c.situacao = ‘Ativo’
and s.idcontato is null
group by m.idcontato

nao retornou nada, deveria retornar o valor 15 oq seria o s ??

M

deu pra entender??

idcontato = 15
idcontato = 16

mes atual janeiro

vou gerar as mensalidades, porem o idcontato 15 ja esta cadastrado na tabela mensalidade como quem ja pagou a mensalidade de janeiro, entao com a sql eu retornaria somente o idcontato = 16 ai eu iria gerar a mensalidade do mes de janeiro para o idcontato = 16 e o m.pago ficaria 0 pois ele ainda nao pagou, so quem tem o m.pago= 1 que ja pagou ou seja, o idcontato 15, por isso eu uso o not in para nao vir quem ja pagou ou quem ja esta cadastrado como inadimplente no mes que estou fazendo a consulta

E

Então, creio que na sua sql está sobrando uma condição or m.pago=‘0’ não?

select m.idcontato from mensalidade m inner join contato c left join ( select m.idcontato from mensalidade m where m.mes= 'JANEIRO' and m.pago ='1' ) s on m.id_contato = s.id_contato where c.situacao = 'Ativo' and s.idcontato is null group by m.idcontato

M

nao, porque o funcionario pode acidentalmente cadastrar o funcionario no mes posterior como devedor, sabe como e usuario ne?

e sua consulta nao ta retornando valor nenhum, oq seria o S que vc utiliza?

M

sem o or m.pago=‘0’ retorna o valor 15

E

tá difícil de entender assim, tenta fazer o seguinte, posta os create tables das suas tabelas (com as pk’s também), e tenta explicar melhor o que você quer.

M

porem, agora no banco eu tenho o mes de janeiro com m.pago=0 para o idcontato 15 entao nao deveria retornar o valor de idcontato 15 pois ja tem cadastrado no banco como pago ou nao pago, o importante e nao gerar a mensalidade paga ou nao paga para o mes que ja esta cadastrado para o idcontato.

M

evefuji segue:
Tabela Contatos:

CREATE TABLE  `bdmensalidade`.`contato` (
  `idcontato` int(20) NOT NULL AUTO_INCREMENT,
  `matricula` int(20) DEFAULT NULL,
  `nomecompleto` varchar(50) DEFAULT NULL,
  `dt_nascimento` date DEFAULT NULL,
  `identidade` varchar(20) DEFAULT NULL,
  `orgaoexpedidor` varchar(7) DEFAULT NULL,
  `cpf` varchar(20) DEFAULT NULL,
  `tituloeleitoral` varchar(15) DEFAULT NULL,
  `celular` varchar(13) DEFAULT NULL,
  `telefone` varchar(13) DEFAULT NULL,
  `email` varchar(100) DEFAULT NULL,
  `situacao` varchar(15) DEFAULT NULL,
  PRIMARY KEY (`idcontato`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=latin1

Tabela mensalidades:

CREATE TABLE  `bdmensalidade`.`mensalidade` (
  `idmensalidade` int(20) NOT NULL AUTO_INCREMENT,
  `idcontato` int(20) NOT NULL,
  `mesref` int(2) DEFAULT NULL,
  `mes` varchar(20) DEFAULT NULL,
  `ano` int(10) DEFAULT NULL,
  `datacadastro` date DEFAULT NULL,
  `pago` varchar(3) DEFAULT '0',
  PRIMARY KEY (`idmensalidade`),
  KEY `FK_CONTATO` (`idcontato`),
  CONSTRAINT `FK_CONTATO` FOREIGN KEY (`idcontato`) REFERENCES `contato` (`idcontato`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1

oq eu preciso fazer é, pegar o idcontato do cliente que não esteja com valor 0 ou 1 na coluna pago da tabela mensalidade e com valor Ativo na coluna situacao da tabela contato referente ao mes que eu digitar no jsp.

ex:

quero consultar o idcontato que esteja Ativo na coluna situacao da tabela contato e que nao esteja com valor 0 ou 1 na coluna pago da tabela mensalidade referente ao mes de janeiro que fica na coluna mes da tabela mensalidade.

agora expliquei corretamente?

forte abraço

neno

Deixa eu ver se eu entendi, sua intenção é gerar mensalidades do mes que vc escolhe, e vc so quer pegar os contatos que não possuem a mensalidade que vc escolheu gerada, é isso?

eu acho que é assim é o suficiente mouze…
acho que nao precisa levar a coluna pago em consideração, ja que ela so pode ser 0 ou 1, e vc não quer nenhuma das duas…

SELECT
c.idcontato
FROM
contato c
WHERE
c.situacao = “ativo”
AND NOT EXISTS(SELECT * from mensalidade m WHERE m.idcontato = c,idcontato AND m.mes = “JANEIRO” );

E

tenta assim(Vê se eu entendi corretamente):

select
from (
  select
    c.idcontato
  from contato
  where situacao = 'ativo'
) c
left join (
  select idcontato   
  from mensalidade
  where mes= 'JANEIRO'    
    and pago in ('1', '0')
) m
on c.idcontato = m.idcontato
where m.id_contato is null
E

neno:
Deixa eu ver se eu entendi, sua intenção é gerar mensalidades do mes que vc escolhe, e vc so quer pegar os contatos que não possuem a mensalidade que vc escolheu gerada, é isso?

eu acho que é assim é o suficiente mouze…
acho que nao precisa levar a coluna pago em consideração, ja que ela so pode ser 0 ou 1, e vc não quer nenhuma das duas…

SELECT
c.idcontato
FROM
contato c
WHERE
c.situacao = “ativo”
AND NOT EXISTS(SELECT * from mensalidade m WHERE m.idcontato = c,idcontato AND m.mes = “JANEIRO” );

neno, usar subconsulta no where fica muito pesado em tabelas muito grandes, é recomendável, para esses casos, usar um left join verificando se é null, como no exemplo que eu dei acima.

E sobre a coluna pago, ele não disse que não aceita outros valores além de 0 ou 1.

M

evefuji deu um erro no sql que me enviou, mas eu consegui com a dica do neno, muito obrigado aos 2 pela ajuda!!

E

mouzer:
evefuji deu um erro no sql que me enviou, mas eu consegui com a dica do neno, muito obrigado aos 2 pela ajuda!!
heheh, no sql que enviei faltou o campo entre select e from(esqueci)

Mas faça o teste, com cerca de 1 ano de dados deve dar para vc ver a diferença, usa o exists e o left join (da forma que falei), e vê qual é o mais rápido. A diferença de desempenho aumenta exponencialmente em relação a quantidade de registros que você manipula.

select  
  idcontato
from (  
  select  
    c.idcontato  
  from contato  
  where situacao = 'ativo'  
) c  
left join (  
  select idcontato     
  from mensalidade  
  where mes= 'JANEIRO'      
    and pago in ('1', '0')  
) m  
on c.idcontato = m.idcontato  
where m.id_contato is null
Criado 11 de novembro de 2010
Ultima resposta 11 de nov. de 2010
Respostas 15
Participantes 3