Logo Hardware.com.br
HenriqueSilva
HenriqueSilv... Novo Membro Registrado
3 Mensagens 2 Curtidas

[Resolvido] Calcular intervalo de tempo em postgresql

#1 Por HenriqueSilv... 13/01/2016 - 16:03
Bom dia! Considerando o código sql "SELECT * FROM public.domotica_log order by item_id, dia;" que retorna o seguinte:

Imagem

Como eu faria para retornar o tempo total que cada objeto (item_id) ficou ligado, entre 01/01/2016 e 10/01/2016?

Obrigado
Shinayder
Shinayder Veterano Registrado
669 Mensagens 118 Curtidas
#3 Por Shinayder
13/01/2016 - 16:35
Relacione o item_id, para que ele traga aquele ID em especifico, caso faça como o Diguin informou, vai dar certo também, porem ele ira trazer o tempo total de todos os itens e não de cada item como você quer.
Phenon X4 Black Box Edition 3.4 64bits | Memoria DDR3 8Gb | Nvidea Geforce GTS 450 1GB| HD Samsung SATA 500Gb e Samsung SATA 1 Tb rindo_atoa.gif
NoteBook: Em Analise nao_sei.gif
http://www.stormclouds.com.br/
HenriqueSilva
HenriqueSilv... Novo Membro Registrado
3 Mensagens 2 Curtidas
#4 Por HenriqueSilv...
13/01/2016 - 17:02
DiguinDeveloper disse:
Algo como:
[code=sql]
SELECT SUM(dia), item_id FROM public.domotica_log
WHERE dia BETWEEN '2016-01-01' AND '2016-01-10'
GROUP BY item_id HAVING tarefa = 'ligou' ORDER BY item_id, dia;
[/code]



Obrigado Diguin mas ainda não deu certo. Não deu pra usar SUM com esse tipo de dado (timestamp with time zone).
Além disso eu acho que é necessário, para cada item, calcular a diferença entre um desligou e o seu ligou antecessor para depois somar todas essas diferenças.
Em caso de a primeira tarefa ser "desligou" tem que considerar que a data que o item foi ligado como sendo a data inicial (2016-01-01).
Em caso de a última tarefa ser "ligou" tem que considerar que a data que o item foi desligado como sendo a data final (2016-01-10).

Só que eu nem imagino como fazer isso em SQL confused.png

É possível fazer isso só com SQL ou vou ter que usar uma linguagem de programação?
Shinayder
Shinayder Veterano Registrado
669 Mensagens 118 Curtidas
#5 Por Shinayder
13/01/2016 - 17:09
Talvez isso resolva

[code=sql]SELECT dia
FROM public.domotica_log
WHERE dia BETWEEN '2016-01-01' AND '2016-01-10'
and item_id = 3
HAVING tarefa = 'ligou'
ORDER BY dia
minus
SELECT dia
FROM public.domotica_log
WHERE dia BETWEEN '2016-01-01' AND '2016-01-10'
and item_id = 3
HAVING tarefa = 'desligou'
ORDER BY dia[/code]
Phenon X4 Black Box Edition 3.4 64bits | Memoria DDR3 8Gb | Nvidea Geforce GTS 450 1GB| HD Samsung SATA 500Gb e Samsung SATA 1 Tb rindo_atoa.gif
NoteBook: Em Analise nao_sei.gif
http://www.stormclouds.com.br/
DiguinDeveloper
DiguinDevelo... Super Participante Registrado
313 Mensagens 148 Curtidas
#6 Por DiguinDevelo...
14/01/2016 - 14:52
O negócio está ficando interessante...

Na documentação do postgresql fala algo sobre operadores e funções com data e hora, e seguindo a lógica, poderia fazer algo assim:
[code=sql]
SELECT SUM(MAX(dia) - MIN(dia)), item_id FROM public.domotica_log
WHERE dia BETWEEN '2016-01-01' AND '2016-01-10'
GROUP BY item_id, MIN(dia), MAX(dia)
HAVING (MIN(dia) > 0 AND tarefa = 'ligou') AND (MAX(dia) > 0 AND tarefa = 'desligou')
[/code]

Bom, fui em outra dimensão com essa query, mas estou deduzindo que se a data que desligou é sempre maior (MAX) que a data que ligou (MIN) basta subtrair que dará o resultado em dias (segundo documentação...) e esse sim, por ser inteiro pode ser somado (SUM), daí o perigo fica lá no group by e having que como falei fui em outra dimensão big_green.png

O having apenas comparo MIN e MAX com zero, pra tentar separar pela tarefa, tanto que forcei precedência pra trazer true and true...

Taí minha contribuição, estou até com o crânio latejando eek.png abraços
esquiloesperto
esquiloesper... Cyber Highlander Moderador
7.1K Mensagens 2.2K Curtidas
#7 Por esquiloesper...
14/01/2016 - 20:35
DiguinDeveloper disse:
Taí minha contribuição, estou até com o crânio latejando eek.png abraços
Heheheee.... faceiro.png
O certo é que esse arquivo está inconsistente, e por causa disto qualquer que seja a resposta ela pode até ser considerada aceitável - porém jamais será a resposta exata.

O grande problema é que faltam neste arquivo os limites de tempo inferior e superior. O limite inferior é o momento de início da tomada das leituras, enquanto o superior é o instante no qual as leituras foram interrompidas para a geração do arquivo de log.
SE estes marcos estivessem presentes, a simples razão mostrada pelo @Shinayder [aqui] seria mais que suficiente.

Tanto faz o SQL ou qualquer linguagem compilada ou interpretada, sem esses limites no máximo será obtido o somatório dos intervalos fechados apenas, deixando de fora os intervalos abertos que também integram o custo e a atividade final dos equipamentos, bem como dos usuários.
Só é difícil enquanto estiver oculto! cool.png
Use a pesquisa


rolleyes.png  Navegar é preciso, viver... também.  smile.png
HenriqueSilva
HenriqueSilv... Novo Membro Registrado
3 Mensagens 2 Curtidas
#8 Por HenriqueSilv...
27/01/2016 - 16:31
Olá, não achei a solução através de SQL mas como eu estou desenvolvendo em Django consegui resolver usando só python mesmo.
No arquivo views.py eu usei este trecho de código:


for item in registros_por_item:
tempo_ligado = [] #LISTA COM OS INTERVALOS DE TEMPO QUE O ITEM FICOU LIGADO
total_tempo_ligado = timedelta() #VARIAVEL COM A SOMA DOS INTERVALOS
j=0
try:
if item[0].tarefa == 'desligou':
tempo_ligado.append(item[0].dia - dia_inicio)

for i in range(len(item)):
if item[i].tarefa == 'desligou':
if i > 0:
tempo_ligado.append(item[i].dia - item[i-1].dia)
j=i

if item[j].tarefa == 'ligou':
tempo_ligado.append(dia_fim - item[j].dia)
except IndexError:
pass

for i in tempo_ligado:
total_tempo_ligado += i

gasto_por_item.append(total_tempo_ligado) #LISTA COM O TOTAL DE HORAS LIGADO DE CADA ITEM


for a in range(len(registros_por_item)):
dicionario[itens[a].descricao]=gasto_por_item[a],arredonda( (float(itens[a].potencia)/1000)*gasto_por_item[a].seconds/3600 )


No template eu adicionei este trecho:
    <h1>Consumo em Horas</h1>
<ul>
{% for key, value in dicionario.items %}
<li><b>{{key}}</b> - {{value.0}}</li>
{% endfor %}
</ul>

<h1>Consumo em KW/h</h1>
<ul>
{% for key, value in dicionario.items %}
<li><b>{{key}}</b> - {{value.1}}</li>
{% endfor %}
</ul>


O resultado ficou assim:

Imagem
Agora falta só arrumar uns detalhes. Obrigado a todos que ajudaram.
© 1999-2024 Hardware.com.br. Todos os direitos reservados.
Imagem do Modal