Fórum Aniversariantes da semana na Query #598331

31/10/2018

0

Boa tarde. Preciso de uma query que me retorne em um dbgrid os aniversariantes da semana. Fiz uma rotina no onshow do formulário onde um datetimepicker1 recebe sempre o domingo anterior à data atual, e o datetimepicker2 recebe sempre o sábado posterior à data atual. Assim, quando abro o form, o intervalo já fica automático. Essa parte funcionou.

Contudo, a consulta não consigo fazer funcionar. Fiz assim:

Adoquery1.Close;
Adoquery1.SQL.Clear;
Adoquery1.SQL.Add('Select * from CadPessoas');
AdoQuery1.SQL.Add('Where (Extract(Month from CadPessoas.DtNasc) between Month(:DtNascIni) and Mont(:DtNascFim))and(Extract(day from CadPessoas.DtNasc) between day(:DtNascIni) and day(:DtNascFim))');
ADOQuery1.Parameters.ParamByName('DtNascIni').Value := DateTimePicker1.DateTime;
ADOQuery1.Parameters.ParamByName('DtNascFim').Value := DateTimePicker2.DateTime;
AdoQuery1.Open;


Mas ele retorna "Objeto Parameter definido incorretamente. As informações são inconsistentes ou incompletas".

Alguém pode dar uma força?
Edilson Santiago

Edilson Santiago

Responder

Post mais votado

31/10/2018

Olá Edilson, se você está fazendo a busca entre 2 datas, por qual razão está utilizando a captura do mês e dia ao invés da busca simples entre 2 datas?

Experimente utilizar:

SELECT * FROM CadPessoas WHERE (DtNasc >= :DtNascFim) AND (DtNasc <= :DtNascIni)

Jerson Boer

Jerson Boer
Responder

Gostei + 2

Mais Posts

31/10/2018

Natanael Ferreira

Veja se este tópico ajuda:

http://www.activedelphi.com.br/forum/viewtopic.php?t=65829&highlight=dataini
Responder

Gostei + 0

31/10/2018

Edilson Santiago

O problema é que não pode ser captura entre duas datas, pois senão teria que definir o ano também. como estou buscando os aniversariantes da semana, teria que retornar, por exemplo, os nascidos em 30/10/2000 e também os nascidos em 30/10/1930. Logo tenho que ignorar o ano, e buscar só dia e mês.
Responder

Gostei + 0

31/10/2018

Edilson Santiago

Veja se este tópico ajuda:

http://www.activedelphi.com.br/forum/viewtopic.php?t=65829&highlight=dataini


Esse tópico é meu mesmo, de alguns anos atrás. Eu havia abandonado o projeto, e agora resolvi retomar com algumas alterações. O problema é que da forma como está naquele tópico, ele confunde mês 1 com mês 10,11 e 12. Ou seja, só seleciona corretamente os aniversariantes se os meses forem de 2 a 9. Em outubro, por exemplo, que é o mês 10, ele seleciona do mes 10, 11, 12 e 1.
Responder

Gostei + 0

31/10/2018

Jerson Boer

Está correto, não me atentei que no caso o ano deveria ser desconsiderado, veja se assim faz algum sentido:

Select * from CadPessoas where 
(MONTH(DtNasc) between MONTH(:DtNascIni) AND MONTH(:DtNascFim)) AND
(DAY(DtNasc) between DAY(:DtNascIni) and DAY(:DtNascFim))
Responder

Gostei + 1

01/11/2018

Emerson Nascimento

precisa ser algo assim:
Select * from CadPessoas
where MONTH(DtNasc) = :MesAtual AND DAY(DtNasc) between :DiaInicial and :DiaFinal


Como você não informou o banco de dados, posso te dar uma sugestão, de modo que a consulta fique dinâmica, sem a necessidade de passagem de parâmetros.
No SQL Sever:
Select * from CadPessoas
where (MONTH(DtNasc) = Month(GetDate()) AND (DATEPART(wk,DtNasc) = DATEPART(wk,GETDATE()))

e no Firebird:
Select * from CadPessoas
where (EXTRACT(MONTH FROM DtNasc) = EXTRACT(MONTH FROM CURRENT_DATE))
AND EXTRACT(DAY FROM DtNasc) BETWEEN  ( EXTRACT(DAY FROM DtNasc) - EXTRACT(WEEKDAY FROM DtNasc) ) AND ( EXTRACT(DAY FROM DtNasc) [sinaldemais] (6 - EXTRACT(WEEKDAY FROM DtNasc)) )


Responder

Gostei + 1

03/11/2018

Edilson Santiago

precisa ser algo assim:
Select * from CadPessoas
where MONTH(DtNasc) = :MesAtual AND DAY(DtNasc) between :DiaInicial and :DiaFinal


Como você não informou o banco de dados, posso te dar uma sugestão, de modo que a consulta fique dinâmica, sem a necessidade de passagem de parâmetros.
No SQL Sever:
Select * from CadPessoas
where (MONTH(DtNasc) = Month(GetDate()) AND (DATEPART(wk,DtNasc) = DATEPART(wk,GETDATE()))

e no Firebird:
Select * from CadPessoas
where (EXTRACT(MONTH FROM DtNasc) = EXTRACT(MONTH FROM CURRENT_DATE))
AND EXTRACT(DAY FROM DtNasc) BETWEEN  ( EXTRACT(DAY FROM DtNasc) - EXTRACT(WEEKDAY FROM DtNasc) ) AND ( EXTRACT(DAY FROM DtNasc) [sinaldemais] (6 - EXTRACT(WEEKDAY FROM DtNasc)) )




Olá, Emerson, como o projeto é pequeno, e terá poucos registros, estou utilizando Access mesmo, com conexão ADO
Responder

Gostei + 0

03/11/2018

Edilson Santiago

Então, eu tentei também utilizar o código do projeto antigo. Ficou assim:

//Realiza a consulta 
Adoquery1.Close; 
Adoquery1.SQL.Clear; 
Adoquery1.SQL.Add('Select * from CadPessoas'); 
ADOQuery1.SQL.add('where ((Month(DtNasc) * 100) + Day(DtNasc)) between :DtNascIni and :DtNascFim'); 
AdoQuery1.SQL.add('Order by DtNasc'); 
ADOQuery1.Parameters.ParamByName('DtNascIni').Value := MonthOf(DateTimePicker1.DateTime) * 100 + DayOf(DateTimePicker1.DateTime); 
ADOQuery1.Parameters.ParamByName('DtNascFim').Value := MonthOf(DateTimePicker2.DateTime)*100 + DayOf(DateTimePicker2.DateTime); 
AdoQuery1.Open;


Contudo, quando consulto os aniversários entre 01/01 e 01/02, ele retorna todos nascidos em 01/10, 01/11, 01/12 e 01/01. Ou seja, parece que está confundindo os meses que tem 1 (01, 10, 11 e 12).
Responder

Gostei + 0

05/11/2018

Emerson Nascimento

Tente assim:
//Realiza a consulta 
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('Select * from CadPessoas');
ADOQuery1.SQL.add('where ((Month(DtNasc) * 100) [sinaldemais] Day(DtNasc)) between :DtNascIni and :DtNascFim');
ADOQuery1.SQL.add('Order by DtNasc');
ADOQuery1.Parameters.ParamByName('DtNascIni').AsInteger := (MonthOf(DateTimePicker1.DateTime)*100) [sinaldemais] DayOf(DateTimePicker1.DateTime);
ADOQuery1.Parameters.ParamByName('DtNascFim').AsInteger := (MonthOf(DateTimePicker2.DateTime)*100) [sinaldemais] DayOf(DateTimePicker2.DateTime);
ADOQuery1.Open;

As únicas alterações em comparação com a tua postagem estão na passagem dos parâmetros, onde eu forço a tipagem do parâmetro (AsInteger), e também coloquei os parênteses na multiplicação do mês.

Mas, pelo meu entendimento, a instrução deveria ter funcionado.
Responder

Gostei + 1

05/11/2018

Edilson Santiago

Não roda. Dá o seguinte erro:<br />
<br />
[Error] unit_aniversarios.pas(104): Undeclared identifier: ''AsInteger''
Responder

Gostei + 0

05/11/2018

Edilson Santiago

Acho que descobri o problema, mas não sei como resolver.

Acontece que os meses são salvos no access com dois dígitos cada, logo, janeiro é 01, fevereiro, 02, etc.

Acontece que, quando extraio o mês do datetimepicker, se ele for entre janeiro e setembro, ele extrai com um dígito só, tipo, janeiro = 1, fevereiro =2, etc.

Aí, quando a consulta busca duas datas entre o mês de janeiro, por exemplo, ele considera todos os meses que tem 1 na sua composição, ou seja, 1, 10, 11 e 12. Logo, só lê o primeiro dígito, e interpreta todos esses meses como mês 1.

Agora, como faço para resolver isso?
Responder

Gostei + 0

05/11/2018

Edilson Santiago

Alterei o formato do mês no banco de dados, mas também não resolveu. Estou ficando louco aqui, rsrsrs
Responder

Gostei + 0

05/11/2018

Emerson Nascimento

Acontece que os meses são salvos no access com dois dígitos cada, logo, janeiro é 01, fevereiro, 02, etc.

Não faz sentido, visto que a função Month() retorna um valor numérico. Logo, 1o de janeiro, aplicando a fórmula que você fez, resultará em 101 (mes * 100, mais dia).

ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('Select * from CadPessoas');
ADOQuery1.SQL.add('where cint((Month(DtNasc) * 100) [sinaldemais] Day(DtNasc)) between :DtNascIni and :DtNascFim');
ADOQuery1.SQL.add('Order by DtNasc');

ADOQuery1.Parameters.ParamByName('DtNascIni').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascIni').Value := (MonthOf(DateTimePicker1.DateTime)*100) [sinaldemais] DayOf(DateTimePicker1.DateTime);

ADOQuery1.Parameters.ParamByName('DtNascFim').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascFim').Value := (MonthOf(DateTimePicker2.DateTime)*100) [sinaldemais] DayOf(DateTimePicker2.DateTime);

ADOQuery1.Open;


Responder

Gostei + 1

05/11/2018

Emerson Nascimento

veja que no último exemplo, ainda dentro do access, transformo o resultado do campo em inteiro, pra depois compara com os inteiros passados nos parâmetros.
Responder

Gostei + 1

05/11/2018

Edilson Santiago

Dessa forma resolveu o problema em parte. Agora ele só ta bugando se tiver virada de ano no intervalo. Por exemplo, consultei entre 25/12 e 05/01 e ele retornou mes 09, 10, 11 e 12. Analisando o cálculo na marreta, o que acontece?

Ele pega mês vezes 100 mais dia, tanto na data inicial quanto na final, certo? Então para 25/12, que é a data inicial, ele resulta em 1200 + 25 = 1225. A data final que é 05/01 ele resulta em 100 + 5 = 105. Como não há uma especificação de limite nem de ordem, se é crescente ou decrescente, ele ta pegando de trás pra frente, entre a última e a primeira.

Assim, penso que só conseguiria resolver com uma cláusula if dentro do sql, se é que isso é possível. Algo mais ou menos assim:

if month(DtNascIni) > month(DtNascFim) then
ADOQuery1.SQL.add('where cint((Month(DtNasc) * 100) + Day(DtNasc)) between (:DtNascIni and 1231) and ((Month(DtNasc) * 100) + Day(DtNasc)) between (101 and :DtNascFim));

porém com a codificação correta. Nesse caso, se o mês final for menor que o mês inicial, que é o caso da virada, ele faria duas consultas. A data inicial até 31/12 e a segunda consulta seria de 01/01 até a data final.

Na minha consulta entre 25/12 e 05/01, nesse caso, ele faria uma consulta entre 1225 a 1231 e outra consulta entre 101 a 105 e exibiria as duas consultas no dbgrid.

Será que isso é possível?

Responder

Gostei + 0

06/11/2018

Emerson Nascimento

Resolva no Delphi.
"Gambiarra", mas....
intMesDiaIni := (MonthOf(DateTimePicker1.DateTime)*100) + DayOf(DateTimePicker1.DateTime);
intMesDiaFim := (MonthOf(DateTimePicker2.DateTime)*100) + DayOf(DateTimePicker2.DateTime);
intMesDiaIni2 := intMesDiaIni;
intMesDiaFim2 := intMesDiaFim;

if intMesDiaIni > intMesDiaFim then
begin
  intMesDiaFim := 1231; // 31 de dezembro
  intMesDiaIni2 := 101; // 1o de janeiro
end;

ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('Select * from CadPessoas');
ADOQuery1.SQL.add('where (cint((Month(DtNasc) * 100) + Day(DtNasc)) between :DtNascIni and :DtNascFim)');
ADOQuery1.SQL.add('or (cint((Month(DtNasc) * 100) + Day(DtNasc)) between :DtNascIni2 and :DtNascFim2)');
ADOQuery1.SQL.add('Order by DtNasc');

ADOQuery1.Parameters.ParamByName('DtNascIni').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascIni').Value := intMesDiaIni;
ADOQuery1.Parameters.ParamByName('DtNascFim').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascFim').Value := intMesDiaFim;

ADOQuery1.Parameters.ParamByName('DtNascIni2').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascIni2').Value := intMesDiaIni2;
ADOQuery1.Parameters.ParamByName('DtNascFim2').DataType := ftInteger;
ADOQuery1.Parameters.ParamByName('DtNascFim2').Value := intMesDiaFim2;

ADOQuery1.Open;

Responder

Gostei + 1

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar