Campo datetime

29 views
Skip to first unread message

Andre Fernando Dominguez

unread,
Jan 31, 2012, 3:19:04 PM1/31/12
to sql-serv...@googlegroups.com, sqlse...@googlegroups.com
Boa Tarde pessoal

Estou tendo problemas em um campo datetime, onde armazeno a data e a
hora de uma determinada ação.
Por exemplo, tenho uma tabela onde é registrada a entrada e a saída
de usuários por uma catraca de acesso. O registro é feito em um campo
datetime e armazenado data e hora completa.

O registro fica assim

nome - dataentrada - datasaida
andre - 2012-01-01 00:30:00 - null
andre - null - 2012-01-01 00:33:00
roberto - null - 2012-01-01 00:45:00
roberto - 2012-01-01 00:46:00 - null
andre - 2012-01-01 00:50:00 - null

Até ai tudo bem, num select consigo trazer a data separada da hora com
o seguinte comando:

SELECT nome, CONVERT(VARCHAR(12), catracaacesso.dataentrada,103) as
'data_entrada' FROM catracaacesso WHERE dataentrada='2012-01-01'

Com este select a saída seria

nome - dataentrada
andre - 01-01-2012
roberto - 01-01-2012
andre - 01-01-2012


isso me resolve parcialmente, pois tenho varias entradas e varias
saídas num mesmo dia de um mesmo funcionário, quando mando contar as
entradas ele nao totaliza pois o campo tem a hora por isso ele nao
consegue contar ( acredito eu ).

Tem outra maneira de contar esses registros sem ser com o select abaixo?

SELECT nome, CONVERT(VARCHAR(12), catracaacesso.dataentrada,103) as
'data_entrada' FROM catracaacesso, COUNT(nome) as total WHERE
dataentrada='2012-01-01'

nome - dataentrada - total
andre -01-01-2012 - 1
roberto -01-01-2012 - 1
andre - 01-01-2012 - 1

Qual a solução para o meu problema se eu quiser uma saida assim:

nome - dataentrada - total
andre - 01-01-2012 - 2
roberto - 01-01-2012 - 1


--
André Fernando Dominguez
PontoCom Informatica
Hospital Regional de Colider

Já dizia Arnaldo Jabor
Ninguém ama outra pessoa pelas qualidades que ela tem,
caso contrário os honestos, simpáticos e não fumantes
teriam uma fila de pretendentes batendo a porta

Rodrigo Ribeiro Gomes

unread,
Jan 31, 2012, 6:28:15 PM1/31/12
to sqlse...@googlegroups.com, sql-serv...@googlegroups.com
André se eu entendi seu problema você pode fazer assim:

SELECT
A.nome
,A.DataEntrada
,COUNT(A.nome)
FROM
(
SELECT
CA.nome
,CONVERT(VARCHAR(12), CA.dataentrada,103) as DataEntrada
FROM
catracaacesso CA
WHERE
CA.dataentrada IS NOT NULL
) A
GROUP BY
A.nome
,A.DataEntrada


A tabela derivada A, gera um resultado contendo O nome e a data sem as horas, e em cima desse resultado a agrupação é feita.
Este é um efeito bem interessante do processamento lógico da query:

Primeiro o FROM é processado, isto é, os joins e cláusula ON.
Depois o WHERE é aplicado sobreo o resultado do JOIN.
Ai vem o GROUP BY e agrupa os dados com base nas colunas especificadas, isso na saída do WHERE. 
E depois vem o HAVING (se houver).
Por último vem o SELECT, processando as expressoes, inluindo as funoes agregadas.

Assim, na fase do GROUP BY, que é antes da fase do SELECT, a coluna DataAcesso foi agrupada com seus valores originais, isso é, incluindo a hora, e a hora foi retirada apenas na fase do SELECT, mas internamente os grupos sao com base no tipo DateTime.

Cara, desculpe se isso ficou confuso, qualquer coisa só falar...


Ah, antes que eu vá, proponho que você utilize esse cara, caso utilize o SQL Server 2008:

SELECT
A.nome
,CONVERT(varchar(12),A.DataEntrada,103) as DataEntrada
,COUNT(A.nome)
FROM
(
SELECT
CA.nome
,CONVERT(date, CA.dataentrada) as DataEntrada
FROM
catracaacesso CA
WHERE
CA.dataentrada IS NOT NULL
) A
GROUP BY
A.nome
,A.DataEntrada


A diferença é que na tabela derivada eu converto pra DATE (que é um tipo de dado incluído no SQL Server 2008). Porque eu fiz isso ?
Porque quando o sql server for comparar as linhas pra agrupar o "nome" e "dataacesso" iguais ele vai comparar 3 bytes em vez de 12 (que é o tamanho da data em varchar). Os 3 bytes a que me refiro é do tipo date, que ocupa somente 3 bytes.

Pra finalizar, e a titulo de curiosade resolvi comparar o tempo, pra ver se minha suspeita estava certa:

DECLARE @TempoIni datetime, @TempoFim datetime

SET @TempoIni = CURRENT_TIMESTAMP

SELECT
A.nome
,A.DataEntrada
,COUNT(A.nome)
FROM
(
SELECT
CA.nome
,CONVERT(VARCHAR(12), CA.dataentrada,103) as DataEntrada
FROM
catracaacesso CA
WHERE
CA.dataentrada IS NOT NULL
) A
GROUP BY
A.nome
,A.DataEntrada
SET @TempoFim = CURRENT_TIMESTAMP
SELECT 'Tempo agregado com varchar',DATEDIFF(MS,@TempoIni,@TempoFim)
SET @TempoIni = CURRENT_TIMESTAMP

-- SQL Server 2008
SELECT
A.nome
,CONVERT(varchar(12),A.DataEntrada,103) as DataEntrada
,COUNT(A.nome)
FROM
(
SELECT
CA.nome
,CONVERT(date, CA.dataentrada) as DataEntrada
FROM
catracaacesso CA
WHERE
CA.dataentrada IS NOT NULL
) A
GROUP BY
A.nome
,A.DataEntrada
SET @TempoFim = CURRENT_TIMESTAMP
SELECT 'Tempo agregado com date',DATEDIFF(MS,@TempoIni,@TempoFim)

E, tcharam, aqui na minha máquina (P4 32 bits 512 RAM) a segunda query foi cerca de 200 milisegundos mais rápida (grande diferença!) com 467478 linhas na tabela em mais de 3 tentativas!

Cara, se eu viajei muito e acabei nao te respodendo, foi mal, de novo, qualquer coisa só falar!!!

[]'s

Rodrigo Ribeiro Gomes
MTA | MCTS


Reply all
Reply to author
Forward
0 new messages