Vejo sempre em fóruns muitos usuários com dúvidas sobre cálculos com datas, então resolvi postar alguns exemplos deste cálculo utilizando as funções DATEDIFF, DATEPART e DATEWEEK.
As funções funcionam desde a versão SQL2005. Na versão 2012 temos outras que devem ser material de um próximo tópico.
Em todos os exemplos, estou supondo que o campo de data esta como DATETIME ou SMALLDATETIME e a language como english.
As funções funcionam desde a versão SQL2005. Na versão 2012 temos outras que devem ser material de um próximo tópico.
Em todos os exemplos, estou supondo que o campo de data esta como DATETIME ou SMALLDATETIME e a language como english.
Primeiro vamos conhecer os tipos de datas convertidas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| SELECT CONVERT(VARCHAR(12),GETDATE(),101) AS '101', --mm/dd/aaaaCONVERT(VARCHAR(12),GETDATE(),102) AS '102', --aa.mm.ddCONVERT(VARCHAR(12),GETDATE(),103) AS '103', --dd/mm/aaaaCONVERT(VARCHAR(12),GETDATE(),104) AS '104', --dd.mm.aaCONVERT(VARCHAR(12),GETDATE(),105) AS '105', --dd-mm-aaCONVERT(VARCHAR(12),GETDATE(),106) AS '106', --dd mês aaCONVERT(VARCHAR(12),GETDATE(),107) AS '107', --Mês dd, aaCONVERT(VARCHAR(12),GETDATE(),108) AS '108', --hh:mi:ssCONVERT(VARCHAR(12),GETDATE(),109) AS '109', --mês dd aaaa hh:mi:ss:mmmAM (ou PM)CONVERT(VARCHAR(12),GETDATE(),110) AS '110', --mm-dd-aaCONVERT(VARCHAR(12),GETDATE(),111) AS '111', --aa/mm/ddCONVERT(VARCHAR(12),GETDATE(),112) AS '112', --aammddCONVERT(VARCHAR(12),GETDATE(),113) AS '113', --dd mês aaaa hh:mi:ss:mmm (24h)CONVERT(VARCHAR(12),GETDATE(),114) AS '114', --hh:mi:ss:mmm(24h)CONVERT(VARCHAR(12),GETDATE(),120) AS '120', --aaaa-mm-dd hh:mi:ss(24h)CONVERT(VARCHAR(12),GETDATE(),121) AS '121' --aaaa-mm-dd hh:mi:ss.mmm(24h) |
Agora um cálculo básico: Cálculo de idade
Para cálculo de idade, utilizo a função DATEDIFF.
Para cálculo de idade, utilizo a função DATEDIFF.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| /* TABELA COM DADOS FICTIOS */declare @tabela table (nome varchar(10), data_nascimento datetime)insert into @tabela values ('nome_01', '1980-01-01')insert into @tabela values ('nome_02', '1990-02-11')insert into @tabela values ('nome_03', '1976-03-21')insert into @tabela values ('nome_04', '1965-04-15')insert into @tabela values ('nome_05', '1986-05-16')insert into @tabela values ('nome_06', '1800-06-17')SELECT * -- TODOS OS REGISTROS , datediff(yy, data_nascimento, getdate()) as idade -- parametro YY ou YEAR para mostrar o resultado em ANOS.FROM @tabela |
–Results
nome data_nascimento idade
nome data_nascimento idade
nome_01 1980-01-01 00:00:00.000 34
nome_02 1990-02-11 00:00:00.000 24
nome_03 1976-03-21 00:00:00.000 38
nome_04 1965-04-15 00:00:00.000 49
nome_05 1986-05-16 00:00:00.000 28
nome_06 1800-06-17 00:00:00.000 214
nome_02 1990-02-11 00:00:00.000 24
nome_03 1976-03-21 00:00:00.000 38
nome_04 1965-04-15 00:00:00.000 49
nome_05 1986-05-16 00:00:00.000 28
nome_06 1800-06-17 00:00:00.000 214
Para ficar mais interessante: Que dia da semana o meu usuário nasceu?
Função: DATEPART com o parametro WEEKDAY
Função: DATEPART com o parametro WEEKDAY
1
2
3
4
5
6
7
| -- DIA 07/06/2014 vai cair que dia da semana?SELECT DATEPART(WEEKDAY,'2014-06-07') -- Results----------- 7 |
Mas o que siginifica este 7?
O DATEPART tem como retorno um campo INT, com isso o número dos dias da semana fica assim:
DOMINGO = 1
SEGUNDA =2
TERCA = 3
QUARTA = 4
QUINTA = 5
SEXTA = 6
SABADO = 7
Portanto dia 07/06/2014 será um Sábado.
O DATEPART tem como retorno um campo INT, com isso o número dos dias da semana fica assim:
DOMINGO = 1
SEGUNDA =2
TERCA = 3
QUARTA = 4
QUINTA = 5
SEXTA = 6
SABADO = 7
Portanto dia 07/06/2014 será um Sábado.
Porém fica complicado usar um CASE para cada dia da semana, então agora vamos usar o DATENAME que tem como retorno o dia da semana por extenso:
1
2
3
4
5
| SELECT DATENAME(WEEKDAY,'2014-06-07') -- Results------------------------------Saturday |
Simples?! Agora vamos testar as funções com a seguinte situação:
Fechamento de horas de cartão de ponto, onde eu tenha que contar somente os dias da semana (segunda a sexta)
Neste caso, não temos tabelas com feriados, portanto vale de segunda a sexta.
Fechamento de horas de cartão de ponto, onde eu tenha que contar somente os dias da semana (segunda a sexta)
Neste caso, não temos tabelas com feriados, portanto vale de segunda a sexta.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| CONTA AS HORAS ÚTEIS ENTRE A DATA INICIAL (@INICIO)E A DATA FINAL (@FINAL)*****************************************************/CREATE function fn_HorasUteis ( @dt_inicio smalldatetime, @dt_final smalldatetime)returns varchar(max)asbeginDECLARE @fimdesemana INTDECLARE @i INT/**** CALCULO DE FINAL DE SEMANA ****/SELECT @fimdesemana = 0, @i = 0 WHILE (DATEDIFF(day, @dt_inicio, @dt_final) > @i) BEGIN SELECT @i = @i + 1 IF (DATEPART(WEEKDAY, DATEADD(day, @i, @dt_inicio)) in (1,7)) BEGIN SELECT @fimdesemana = @fimdesemana + 1 ENDENDdeclare @dia numeric(30),@hora numeric(30), @minuto numeric(30) SELECT @dia = DATEDIFF(d, @dt_inicio, @dt_final) SELECT @hora = DATEDIFF(hour, @dt_inicio, @dt_final) select @minuto = DATEDIFF(MINUTE, @dt_inicio, @dt_final) if @dia > 0 begin SET @fimdesemana = (@fimdesemana * 8) SET @hora = @hora - (@dia * 24) - @fimdesemana SET @dia = @dia * 10 endreturnconvert(varchar(max),(@hora +@dia)) +':'+convert(varchar(max),(@minuto %60))end |
Exemplo de uso:
SELECT dbo.fn_HorasUteis(‘2013-01-29 08:00:00′,’2013-01-29 18:00’)
SELECT dbo.fn_HorasUteis(‘2013-01-29 08:00:00′,’2013-01-29 18:00’)
— Results
10:00
Podemos então alterar nossa primeira tabela para trazer o dia da semana em que o usuário nasceu:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| /* TABELA COM DADOS FICTIOS */declare @tabela table (nome varchar(10), data_nascimento datetime)insert into @tabela values ('nome_01', '1980-01-01')insert into @tabela values ('nome_02', '1990-02-11')insert into @tabela values ('nome_03', '1976-03-21')insert into @tabela values ('nome_04', '1965-04-15')insert into @tabela values ('nome_05', '1986-05-16')insert into @tabela values ('nome_06', '1800-06-17')SELECT * -- TODOS OS REGISTROS , datediff(yy, data_nascimento, getdate()) as idade -- parametro YY ou YEAR para mostrar o resultado em ANOS. , DATENAME(weekday,data_nascimento) as [dia_semana]FROM @tabela |
–Results
nome data_nascimento idade dia_semana
nome data_nascimento idade dia_semana
nome_01 1980-01-01 00:00:00.000 34 Tuesday
nome_02 1990-02-11 00:00:00.000 24 Sunday
nome_03 1976-03-21 00:00:00.000 38 Sunday
nome_04 1965-04-15 00:00:00.000 49 Thursday
nome_05 1986-05-16 00:00:00.000 28 Friday
nome_06 1800-06-17 00:00:00.000 214 Tuesday
nome_02 1990-02-11 00:00:00.000 24 Sunday
nome_03 1976-03-21 00:00:00.000 38 Sunday
nome_04 1965-04-15 00:00:00.000 49 Thursday
nome_05 1986-05-16 00:00:00.000 28 Friday
nome_06 1800-06-17 00:00:00.000 214 Tuesday
Nenhum comentário:
Postar um comentário