Ir para conteúdo
Fórum Script Brasil
  • 0

Select Para Aniversariantes


Vivendo&Aprendendo

Pergunta

Olá galera.

Tenho uma SQL para achar os aniversariantes entre duas datas que o usuário irá digitar, essa sql busca na tabela alunos no campo data de nascimento, o problema é que só encontra tipo:

o aluno Alexandre faz aniversário dia 30/06 para a sql encontrar esse registro o usuario terá que digitar as datas da seguinte forma, aniversariantes entre: 01/01/1981 a 31/12/2007 por exemplo. Sendo que o correto seria digitar 01/01/2007 a 30/06/2007 ai o sistema teria que me mostrar todos os aniversariantes dentre estas datas.

A minha SQl é essa:

      With DmDados.Alunos Do
      Begin
        DmDados.Alunos.Close;
        DmDados.Alunos.SQL.Clear;
        DmDados.Alunos.SQL.Add('Select * From Alunos');
        DmDados.Alunos.SQL.Add('Where DataNasc between :Inicial and :Final');
        DmDados.Alunos.Parameters.ParamByName('Inicial').Value := StrToDate(EdtInicial.Text);
        DmDados.Alunos.Parameters.ParamByName('Final').Value := StrToDate(EdtFinal.text);
        DmDados.Alunos.SQL.Add('Order By Codigo');
        DmDados.Alunos.Open;
      end;

Uso banco Access.

Como posso fazer isso.

Alexandre

Link para o comentário
Compartilhar em outros sites

25 respostass a esta questão

Posts Recomendados

  • 0

Ola amigo...

Bom, não trabalho com access, mas em firebird uso a seguinte sql para fazer isso:

SELECT PESSOAS.NOME_PESSOA, PESSOAS.DATA_NASC
FROM PESSOAS WHERE
   (
      (EXTRACT(MONTH FROM PESSOAS.DATA_NASC) between '5' and '6') and
      (EXTRACT(day FROM PESSOAS.DATA_NASC) between '1' and '31')
   )

Que pega todos os aniversariantes do mês 5 e 6 entre os dias 1 e 31...

Tenta usar ai no access pra ver se funciona....

espero ter ajudado...

T+

Link para o comentário
Compartilhar em outros sites

  • 0

Var
sql :string;
begin


Sql := '   SELECT PESSOAS.NOME_PESSOA, PESSOAS.DATA_NASC
FROM PESSOAS WHERE
   (
      (EXTRACT(MONTH FROM PESSOAS.DATA_NASC) between '''  +Edit1.text+  ''' and '''+Edit2.text+''') and
      (EXTRACT(day FROM PESSOAS.DATA_NASC) between '''+Edit3.text+''' and '''+Edit4.text+''')
   )
';

então use a variavel "sql" para fazer a pesquisa. esse esquema de aspas ' '' assim é importante para que seu comando sql fique com aspas e pra você pegar so o dia ou so o ano ou mês de uma data ex."01/01/2007" use a função "DecodeDate"
procedure TForm1.Button1Click(Sender: TObject);

var
  Present: TDateTime;
  Year, Month, Day, Hour, Min, Sec, MSec: Word;
 begin
  Present:= Now;
  DecodeDate(Present, Year, Month, Day);
  Label1.Caption := 'Today is Day ' + IntToStr(Day) + ' of Month '
    + IntToStr(Month) + ' of Year ' + IntToStr(Year);
  DecodeTime(Present, Hour, Min, Sec, MSec);
  Label2.Caption := 'The time is Minute ' + IntToStr(Min) + ' of Hour '
    + IntToStr(Hour);
end;

Link para o comentário
Compartilhar em outros sites

  • 0

Olá usei desta forma e deu ERRO NÃO ESPECIFICADO.

        DmDados.Alunos.Close;
        DmDados.Alunos.SQL.Clear;
        DmDados.Alunos.SQL.Add('SELECT Alunos.NOME, Alunos.DATANASC FROM Alunos');
        DmDados.Alunos.SQL.Add('Where ((EXTRACT(MONTH FROM Alunos.DATA_NASC) between '''  +EdtInicial.text+  ''' and '''+EdtFinal.text+''') and ');
        DmDados.Alunos.SQL.Add('EXTRACT(day FROM Alunos.DATANASC) between "1" and "31"');
        DmDados.Alunos.SQL.Add('Order By Codigo');
        DmDados.Alunos.Open;

falou

Alexandre

Link para o comentário
Compartilhar em outros sites

  • 0

Olá Erso fiz da seguinte forma e deu o mesmo erro:

      Sql := 'SELECT Alunos.NOME, Alunos.DATANASC FROM Alunos WHERE ((EXTRACT(MONTH FROM Alunos.DATANASC) between '''  +EdtInicial.text+  ''' and '''+EdtFinal.text+''') and (EXTRACT(day FROM Alunos.DATANASC) between '''+EdtInicial.text+''' and '''+EdtFinal.text+'''))';
      DmDados.Alunos.SQL.Add(sql);
      DmDados.Alunos.Open;

Link para o comentário
Compartilhar em outros sites

  • 0
Olá Erso fiz da seguinte forma e deu o mesmo erro:

      Sql := 'SELECT Alunos.NOME, Alunos.DATANASC FROM Alunos WHERE ((EXTRACT(MONTH FROM Alunos.DATANASC) between '''  +EdtInicial.text+  ''' and '''+EdtFinal.text+''') and (EXTRACT(day FROM Alunos.DATANASC) between '''+EdtInicial.text+''' and '''+EdtFinal.text+'''))';
      DmDados.Alunos.SQL.Add(sql);
      DmDados.Alunos.Open;
Vivendo&Aprendendo, provavelmente porque você está concatenando da data inteira (dd/mm/yy) ao invés de apenas o mês e o dia. Vou dar um exemplo utilizando parametrização que, no meu modo de ver, torna a leitura do código mais clara, bem como evita algumas dores de cabeça:
with DmDados do
begin
  Alunos.Close;
  Alunos.SQL.Clear;
  Alunos.SQL.Add('SELECT NOME, DATANASC ');
  Alunos.SQL.Add('FROM Alunos ');
  Alunos.SQL.Add('WHERE EXTRACT(MONTH FROM DATA_NASC) between :MesI and :MesF '
  Alunos.SQL.Add(  'AND EXTRACT(DAY FROM DATANASC) between :DiaI and :DiaF ');
  Alunos.SQL.Add('ORDER BY Codigo');
  Alunos.ParamByName('MesI').AsInteger := MonthOf(EdtInicial.text);
  Alunos.ParamByName('MesF').AsInteger := MonthOf(EdtFinal.text);
  Alunos.ParamByName('DiaI').AsInteger := DayOf(EdtInicial.text);
  Alunos.ParamByName('DiaF').AsInteger := DayOf(EdtFinal.text);
  Alunos.Open;
end;

Obs 1) As funções MonthOf e DayOf estão disponíves na unit DateUtils (a partir do D7 eu sei que tem).

Obs 2) Se você estiver utilizando os componentes da paleta ADO, então onde existe ParamByName, deverá ser substituído por: <dataset>.Parameters.ParamByName(<nome campo>).Value := <valor>;

Obs 3) Nas instruções SQL você não precisa incluir o nome da tabela junto de cada campo (Alunos.NOME), quando há apenas uma tabela definida na cláusula FROM. Se necessário for, fica mais curto a escrita se você utilizar os ALIASES (apelido - ex. FROM Aluno A);

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Olá Micheus muito obrigado pela ajuda, mas continua dando o mesmo erro: ERRO NÃO ESPECIFICADO.

Fiz a sql dessa forma:

      with DmDados do
      begin
        Alunos.Close;
        Alunos.SQL.Clear;
        Alunos.SQL.Add('SELECT NOME, DATANASC ');
        Alunos.SQL.Add('FROM Alunos ');
        Alunos.SQL.Add('WHERE EXTRACT(MONTH FROM DATANASC) between :MesI and :MesF ');
        Alunos.SQL.Add('AND EXTRACT(DAY FROM DATANASC) between :DiaI and :DiaF ');
        Alunos.SQL.Add('ORDER BY Codigo');
        Alunos.Parameters.ParamByName('MesI').Value := MonthOf(StrToDate(EdtInicial.text));
        Alunos.Parameters.ParamByName('MesF').Value := MonthOf(StrToDate(EdtFinal.text));
        Alunos.Parameters.ParamByName('DiaI').Value := DayOf(StrToDate(EdtInicial.text));
        Alunos.Parameters.ParamByName('DiaF').Value := DayOf(StrToDate(EdtFinal.text));
        Alunos.Open;
      end;

O que está errado nela?

Alexandre

Link para o comentário
Compartilhar em outros sites

  • 0

Vivendo&Aprendendo, só no final do seu outro post você mensionou algo que volta e meia faz toda a diferença - o banco de dado utilizado. Também pelo fato de você utilizar minha sugestão, deu para perceber que você está utilizando componentes da paleta ADO - normalmente utilizados com MSAccess.

Volto a reforçar à todos os que lêem este post, para que sempre que a questão envolva SQL, que informem o banco de dado que utilizam.

Vivendo&Aprendendo, ocorre que no MSAccess não tem EXTRACT (FireBird e Interbase sim), no MSAccess e MSSQL você utiliza as funções Year(<data>) Month(<data>) e Day(<data>) para extrair este valores de campos datas. Então altere para:

        ...
        Alunos.SQL.Add('WHERE MONTH(DATANASC) between :MesI and :MesF ');
        Alunos.SQL.Add('AND DAY(DATANASC) between :DiaI and :DiaF ');
        ...

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0
Não deu.........
Não deu o quê - como?

Como questionou o Kikonanet, retorna algum erro? Erro de execução ou compilação? Abriu a consulta normalmente, mas não trouxe registros?

Confirme o exemplo que lhe passei por e-mail e veja se com sua base quente vai funcionar, porque com a de teste que você me enviou eu utilizei exatamente a consulta acima e ficou legal - exceto pelo fato que só havia 01 registro em 15 que continha o campo DATANASC preenchido e então preenchi mais alguns. :huh:

Aproveito para sugerir que você utilize o TDateTimePicker (paleta Win32) no lugar dos TEdit's para a entrada das datas.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Olá Micheus e Kiko

Olha usei a sql que o Micheus me enviou pelo e-mail, ela não nenhum erro, mas acontece que não retorna os dados de forma correta, ou seja: se eu digitar no edit inicial a data 01/01/2007, ou apenas 01/01 ou 01/01/1981 e no edit final a data 30/06/2007, ou 30/06 ou 30/06/1981 o correto seria ele me retornar apenas as pessoas que farão aniversarios neste intervalo de datas, mas ele esta retornando registros que não tem nada a ver com a consulta, pelo menos é o que eu acho.

Eu preenchi todos os campos DATANASC no banco com datas diferentes e fiz o teste e deu nisso.

Tenho as seguintes datas em minha tabela:

05/07/1965
10/11/1978
12/01/1980
20/03/1980
15/12/1980
29/06/1981
30/06/1981
30/07/1981
10/10/1981
25/12/1984
07/06/1987
04/09/1988
30/05/1990
01/01/2000
17/01/2007
Fiz a consulta usando as datas 01/01/2007 a 30/06/2007, ele teria que me retornar 8 registro que são os seguinte:
12/01/1980
20/03/1980
29/06/1981
30/06/1981
07/06/1987
30/05/1990
01/01/2000
17/01/2007

Mas acontece que ele me retornou 11 registros, 7 corretos e 4 errados, ele retirou um correto e colocou outros que não deveriam aparecer na consulta, tipo nascidos no mês 12.

KIKO o meu campo DATANASC é do tipo DATA/TIME.

Micheus eu acho que não posso usar o TDateTimePicker pois também uso estes edits para consulta com código.

Pessoal não sei mais o que pode ser.

Vejam ai se vocês tem outra idéia, ou eu que estou fazendo algo errado ainda.

Alexandre

Link para o comentário
Compartilhar em outros sites

  • 0
se eu digitar no edit inicial a data 01/01/2007, ou apenas 01/01 ou 01/01/1981 e no edit final a data 30/06/2007, ou 30/06 ou 30/06/1981 o correto seria ele me retornar apenas as pessoas que farão aniversarios neste intervalo de datas, mas ele esta retornando registros que não tem nada a ver com a consulta, pelo menos é o que eu acho.

Quando você pega do Edit, como você está separando o mês e a data?

Alunos.SQL.Add('WHERE MONTH(DATANASC) between :MesI and :MesF ');
Alunos.SQL.Add('AND DAY(DATANASC) between :DiaI and :DiaF ');

Qual são os valores de MesI, MesF, DiaI, DiaF?

abs.

Kiko

Link para o comentário
Compartilhar em outros sites

  • 0

Esta desta forma KIKO:

      with DmDados.Alunos do
      begin
        Close;
        SQL.Clear;       //NOME, DATANASC
        SQL.Add('SELECT * ');
        SQL.Add('FROM Alunos ');
        SQL.Add('WHERE MONTH(DATANASC) between :MesI and :MesF ');
        SQL.Add('AND DAY(DATANASC) between :DiaI and :DiaF ');
        SQL.Add('ORDER BY Codigo');
        Parameters.ParamByName('MesI').Value := MonthOf(StrToDate(EdtInicial.text));
        Parameters.ParamByName('MesF').Value := MonthOf(StrToDate(EdtFinal.text));
        Parameters.ParamByName('DiaI').Value := DayOf(StrToDate(EdtInicial.text));
        Parameters.ParamByName('DiaF').Value := DayOf(StrToDate(EdtFinal.text));
        Open;
      end;

Link para o comentário
Compartilhar em outros sites

  • 0
Olá Micheus e Kiko

Olha usei a sql que o Micheus me enviou pelo e-mail, ela não nenhum erro, mas acontece que não retorna os dados de forma correta, ou seja: se eu digitar no edit inicial a data 01/01/2007, ou apenas 01/01 ou 01/01/1981 e no edit final a data 30/06/2007, ou 30/06 ou 30/06/1981 o correto seria ele me retornar apenas as pessoas que farão aniversarios neste intervalo de datas, mas ele esta retornando registros que não tem nada a ver com a consulta, pelo menos é o que eu acho.

...

Mas acontece que ele me retornou 11 registros, 7 corretos e 4 errados, ele retirou um correto e colocou outros que não deveriam aparecer na consulta, tipo nascidos no mês 12.

Fazendo a consulta dentro do MSAccess (MSOffice 2000), dá para ver que é coisa do access mesmo. Se você não definir os parâmetros explicitamente ele trata a informação da forma não desejada (tenho uma vaga idéia do motivo em função dos testes).

parameters MesI INTEGER, MesF INTEGER;
SELECT *, DAY(DATANASC)as Dia, MONTH(DATANASC) as mês
FROM Alunos
WHERE MONTH(DATANASC) between MesI and MesF
AND DAY(DATANASC) between 1 and 31
ORDER BY Codigo
Assim, acabou não sendo difícil observar que o problema residia neste fato. Então, alterando um pouco o procedimento, foi possível obter o resultado correto, ou seja, defini o tipo de cada parâmetro antes de atribuir um valor a ele:
...
    Parameters.ParamByName('MesI').DataType := ftInteger;
    Parameters.ParamByName('MesI').Value := MonthOf(StrToDate(EdtInicial.text));
    Parameters.ParamByName('MesF').DataType := ftInteger;
    Parameters.ParamByName('MesF').Value := MonthOf(StrToDate(EdtFinal.text));
    Parameters.ParamByName('DiaI').DataType := ftInteger;
    Parameters.ParamByName('DiaI').Value := DayOf(StrToDate(EdtInicial.text));
    Parameters.ParamByName('DiaF').DataType := ftInteger;
    Parameters.ParamByName('DiaF').Value := DayOf(StrToDate(EdtFinal.text));
...

Isto acaba sendo necessário simplesmente porque você está montando a consulta em tempo de execução.

Se você utilizar umcomponente TADOQuery especificamente para esta consulta (não precisará mudá-lo no código) poderá adicionar o select, em design-time, na propriedade SQL e declarar o tipo dos parâmetros através da edição propriedade Parameters do componente.

Em função do exposto no seu outro post, acredito que seja a melhor opção.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

aí galera do forum o meu problema está resolvido, e quero antes de tudo dar os méritos ao colegas KIKO e MICHEUS, pois eles fizeram de tudo até ver o problema solucionado, é muito bom sabe que temos um forum e contamos com amigos como vocês... muito obrigado. Que Deus sempre abençoe vocês.

Agora falando do problema a consulta sql ficou desta forma:

      with DmDados.Alunos do
      begin
        Close;
        SQL.Clear;
        SQL.Add('SELECT * ');
        SQL.Add('FROM Alunos ');
        SQL.Add('WHERE MONTH(DATANASC) between :MesI and :MesF ');
        SQL.Add('AND DAY(DATANASC) between :DiaI and :DiaF ');
        SQL.Add('ORDER BY DATANASC');
        Parameters.ParamByName('MesI').DataType := ftInteger;
        Parameters.ParamByName('MesI').Value := MonthOf(StrToDate(EdtInicial.text));
        Parameters.ParamByName('MesF').DataType := ftInteger;
        Parameters.ParamByName('MesF').Value := MonthOf(StrToDate(EdtFinal.text));
        Parameters.ParamByName('DiaI').DataType := ftInteger;
        Parameters.ParamByName('DiaI').Value := DayOf(StrToDate(EdtInicial.text));
        Parameters.ParamByName('DiaF').DataType := ftInteger;
        Parameters.ParamByName('DiaF').Value := DayOf(StrToDate(EdtFinal.text));
        Open;
      end;

É só adicionar DB na clausula USES do form.

Alexandre

Link para o comentário
Compartilhar em outros sites

  • 0
Mas que confusão ... porque não fazer :

Sql := 'SELECT NOME_PESSOA, DATA_NASC FROM PESSOAS WHERE month (DATA_NASC) between '  +QuotedStr (Edit1.text)+' and '+QuotedStr (Edit2.text);
Primeiramente, porque a idéia é procurar os aniversariantes baseado no dia e mês (um período é informado) em que o aluno faz o aniversário, e não, simplesmente o mês. E se desejar saber quem faz aniversário esta semana apenas? Segundo, porque sendo informado um período (é o que o colega Vivendo&Aprendendo propôs inicialmente), ainda que utilizando apenas o mês na consulta, você teria que retirá-lo dos seus Edit1.text e Edit2.text - não daria para simplesmente concatená-los.
Deve funcionar com qualquer db sql.
Terceiro, acho que você perdeu esta parte do post. As sugestões iniciais indicavam o uso de EXTRACT, entretanto o MSAccess não tem esta função. É possível observar que uma mesma consulta SQL não pode ser utilizada em todos os bancos. Então, como estava com um tempinho, levantei justamente a questão da manipulação de datas por diversos bancos. Esta é uma questão em que sempre ressalto a validade da utilização de parâmetros, e não a concatenação, nas query's realizadas. Deste modo, no caso da necessidade de comparar/tratar datas, não há necessidade de qualquer preocupação já que ao passar o parâmetro, os driver's que fazem o intermédio entre o banco e a aplicação resolvem estes problemas para nós. Caso alguém tenha alguma correção, por favor faça. Como evidentemente, não conheço todos os bancos citados, coloquei os link's de referência ao lado. Espero que seja útil a alguém. SQLServer - Suporta as funções Day, Month, Year, ... .Não tem a função EXTRACT, porém, a mesma funcionalidade é obtida através da função DatePart (link) MSAccess - Sendo, também, da Micro$oft, vale o que foi escrito para SQLServer (link) MySQL - suporta as funções EXTRACT e Day, Month, Year, ... (link) - Aceita aspas simples ou dupla como delimitador das constantes alfa-numéricas. Como delimitador, o MySQL utiliza o acento grave (crase) - a data, quando concatenada como uma constante, deve estar no formato yyyy-mm-dd. Experimente concater o conteúdo de um edit com a data no formato que foi digitado (dd/mm/yyyy). InterBase/FireBird - até onde sei e apurei, suportam apenas EXTRACT. O uso de funções como Day, Month, Year, ... dependem da instalação de UDF's; - A partir da versão 6, utilizando o Dialect 3 constantes alfa-numéricas devem ser delimitadas por aspas simples. As aspas duplas são utilizadas como delimitador de um identificados (nome de tabela, campo) (link) PostGre - Pelo que levantei, tem apenas EXTRACT (link) Oracle - Pelo que levantei, tem apenas EXTRACT (link - ver Datetime Functions) SyBase Entre as funções para manipulação date/time não há EXTRACT link Paradox - Só dá para utilizar EXTRACT. Inclusive, percebí algo "interessante" com ele. Se contatenar-mos a data como string, poderá ocorrer uma interpretação dúbia. No exemplo abaixo, supondo a contatenação de uma data no formato dd/mm/yyyy (normalmente digitamos assim), seria esperado um resultado positivo, certo?! (observe a cláusula where)
select T.*, extract(month from cast('01/02/2006' as date)) mês
from teste T
where extract(month from cast('01/02/2006' as date)) = 2
Entretanto, nesta situação, o paradox não irá retornar linha alguma, porque ele estará utilizando o formato mm/dd/yyyy. Agora, experimente colocar a consulta desta forma:
select T.*, extract(month from cast('20/02/2006' as date)) mês
from teste T
where extract(month from cast('20/02/2006' as date)) = 2

A princípio, eu alterei apenas o dia de 01 para 20, mas pensando no fato de na consulta anterior o paradox ter interpretado este campo como mês, me parece que deveria ocorrer um erro, não?! Pois então, não ocorre e, neste caso, ele assume a formatação esperada inicialmente dd-mm-yyyy. Isto definitivamente não parece bom!!! (eu testei com o Paradox 7 no Data Base Desktop)

"Mas que confusão ..."

Confusão? Há meios de minimizar esta "confusão", mas pelo tanto que escrevo é melhor deixar para outra oportunidade. ;)

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Vivendo&Aprendendo, com o intúito de resolver as questões referentes aos parâmetros e a função correta para o banco, de modo a que você obtivesse um resultado, uma questão mais importante passou despercebida: A consulta SQL funciona como esperado? E a resposta é não!

Após responder ao post do JPedro (refletindo sobre isso), acabei por perceber que a consulta funciona parcialmente. Vejamos:

1) Período dentro do mesmo mês. Ex. 10/03 - 28/03

2) Período que envolvam mais que um mês, onde o período inicial começa em 01/.. até um mês que termine com 31/..; Desde que dentro do mesmo ano.

WHERE MONTH(DATANASC) between :MesI and :MesF
    AND DAY(DATANASC) between :DiaI and :DiaF
Observe que se solicitamos um período entre 10/01 até 28/02, utilizando a query como está: filtrando aniversariantes nos meses de Jan e Fev e com o dia entre 10 e 28; Logo, ficaremos sem os alunos com aniversário entre os dias 01 a 09 de Jan e Fev, bem como os de 29 a 31 de Jan. Outro, problema também ocorre se o período começar com um mês inicial maior que o final. Por exemplo, num período entre 01/12 a 31/01 (aniversariantes do final e início do próximo ano), substituindo os parâmetros na consulta:
SELECT Alunos.*
FROM Alunos
WHERE MONTH(DATANASC) between 12 and 01
    AND DAY(DATANASC) between 01 and 31;
teremos como resultado todos os alunos, porque no primeiro between, é como se tivesse sido digitado 01 and 12, ou seja todos os meses. Podemos ver, que se a query necessitasse considerar apenas o mês de aniversário, ainda assim, ela não estaria retornando resultados corretos. A sugestão (se tiverem outra mais simples postem, por favor) seria mudar a query dinamicamente (como já é feita), de modo que quando o mês final for maior que o inicial, sejam realizados dois filtros: do mês inicial até o mês 12 e do mês 01 até o mês final. Isto resolveria a questão do filtro por meses. Mas, em nosso caso temos ainda que levar em conta o dia, então, minha sugestão é "concatenar" dia e mês num cálculo. Multiplicaríamos o mês por 100, de mos que somando o dia, obteríamos números crescentes e de fácil comparação. Por ex.: 10/01 até 28/02, teríamos como comparação o cálculo das datas de nascimento com os valores 110 a 228, isto garanteria qualquer resultado intermediário, como 31/01 que seria 131.
var
  DtInicio,
  DtFim :TDateTime;
  Inicio,
  Fim :Integer;
begin
  DtInicio := StrToDate(EdtInicial.text)
  DtFim := StrToDate(EdtFinal.text)
  Inicio := MonthOf(DtInicio) *100 +DayOf(DtInicio);
  Fim := MonthOf(DtFim) *100 +DayOf(DtFim);
  with DmDados.Alunos do
  begin
    Close;
    SQL.Clear;
    SQL.Add('SELECT * ');
    SQL.Add('FROM Alunos ');
    if MonthOf(DtFim) < MonthOf(DtInicio) then
    begin
      SQL.Add('WHERE (Month(DATANASC)*100+Day(DATANASC)) BETWEEN :Inicio AND 1231');
      SQL.Add('    OR (Month(DATANASC)*100+Day(DATANASC)) BETWEEN 101 AND :Fim');
    end else
      SQL.Add('WHERE (Month(DATANASC)*100+Day(DATANASC)) between :Inicio and :Fim');
    SQL.Add('ORDER BY DATANASC');
    Parameters.ParamByName('Inicio').DataType := ftInteger;
    Parameters.ParamByName('Inicio').Value := Inicio;
    Parameters.ParamByName('Fim').DataType := ftInteger;
    Parameters.ParamByName('Fim').Value := Fim;
    Open;
  end;
end;

Se não esqueci de mais alguma coisa...

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0
Olá Micheus...

Mas o que significa os números 1231 e 101 na sql?

seria 31/12 e 01/01. se é isso, porque?

Alexandre

Seriam sim.

O motivo é por aquele que citei. Se você quizer filtrar um período (você não utiliza o ano certo, porque você busca por aniversariantes) onde o mês inicial esteja no final do ano (tipo 15/Nov) até o início do ano seguinte (20/Jan), utilizando a query inicial, você teria - já colocando os valores na query:

WHERE MONTH(DATANASC) between 11 and 1
    AND DAY(DATANASC) between 15 and 20
Ao menso no Access, esta consulta seria a mesma coisa que:
WHERE MONTH(DATANASC) between 1 and 11
    AND DAY(DATANASC) between 15 and 20
Observe que ao invés de obtermos os aniversariantes nos meses NOV, DEZ e JAN, teríamos os com aniversário em JAN, FEV, MAR, ABR, MAI, JUN, JUL, AGO, OUT E NOV. Ainda deixaríamos de fora todos osque fizessem aniversário entre os dias 1 a 14 e 21 a 31. Isto só ocorre porque não comparamos datas, mas sim uma fração delas (dia e mês).
    if MonthOf(DtFim) < MonthOf(DtInicio) then
    begin
      SQL.Add('WHERE (Month(DATANASC)*100+Day(DATANASC)) BETWEEN :Inicio AND 1231');
      SQL.Add('    OR (Month(DATANASC)*100+Day(DATANASC)) BETWEEN 101 AND :Fim');
    end else
      SQL.Add('WHERE (Month(DATANASC)*100+Day(DATANASC)) between :Inicio and :Fim');

utilizando desta forma, pelo menos a princípio, acho que resolvemos o problema. Isso porque se, como exemplifiquei acima, no período final o mês for menor (JAN) do que o inicial (NOV), teremos que considerar dois fragmenos: até DEZ e de JAN em diante. Por isso Inicio a 1231 (31/DEZ) e 101 (01/JAN) a Fim.

De outro modo, basta utilizar do Inicio ao Fim.

Clariou?!

Abraços

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,3k
×
×
  • Criar Novo...