Recover larger and shorter hours conditioned on dates

Asked

Viewed 4,174 times

4

Inside a table containing the columns data_inicio, data_fim, hora_inicio, hora_fim need to identify within a set of records the following occurrences: the lowest start date, the highest end date, the lowest start time and the highest end time.

The image below lists a set of records in which I want to check the lowest start_date, highest end_date, lowest start_time, highest end_time:

inserir a descrição da imagem aqui

Based on the records shown in the image above, the lowest start date is simple to achieve, simply use the operator MIN. The same occurs to get the highest end date. I only need to use the operator MAX to get it. To calculate the highest start time and the lowest end time I cannot use the same approach as can be seen in the sql result below.

SQL:

select min(data_inicio), max(data_fim), min(hora_inicio), max(hora_fim)
from minha_tabela
where codigo = 2

Upshot:

inserir a descrição da imagem aqui

To calculate, both the shorter start time and the longer end time need to take into account more than simply the column itself. Simply use the operator MIN and MAX does not solve. I need to take into account also the columns of dates. Looking at the first image we can notice that the lowest start time is '1000', as the lowest date is '04/05'. The biggest final time is '1900', as the biggest final date is '20/05'.

Is there any way to implement this type of query simply through SQL? If so, how?

This example is in SQL Fiddle.

3 answers

3


First concatenate the date and time columns to transform the string into date:

to_date(data_inicio || ' ' || hora_inicio,'dd-mm-yy hh24mi'))

After that just take the smallest and longest date:

min(to_date(data_inicio || ' ' || hora_inicio,'dd-mm-yy hh24mi')),
max(to_date(data_fim || ' ' || hora_fim,'dd-mm-yy hh24mi'))

And to separate again in just date and/or time:

to_char(min_inicio,'dd/mm/yyyy') menor_data,
to_char(min_inicio,'hh24:mi:ss') menor_hora,
to_char(max_fim,'dd/mm/yyyy') maior_data,
to_char(max_fim,'hh24:mi:ss') maior_hora

See example working on SQL Fiddle.

  • Lucio, I ended up creating my example in SQL Fiddle with the Mysql database which led you to create your answer based on that database. There’s a way you can adapt your answer to Oracle. Use this Sqlfiddle http://sqlfiddle.com/#! 4/d1f13.

  • @Geisonsantos I edited the answer!

  • Lucius, congratulations! Very good your solution. Had achieved in another way a little more verbose. Anyway, your solution got better. I will post my reply later to show others another alternative.

  • Thanks man :) @Geisonsantos

1

Another alternative, a little more verbose, to solve this problem is the use of a temporary table. Initially we recovered this table only with the minimum start date and maximum end date information.

with limites as (
   select min(data_inicio) data_minima, max(data_fim) data_maxima
   from minha_tabela
   where codigo = 2
)

Next we join this table with the table searched to recover the minimum time and the maximum time. This is necessary due to the conditionality of time to date fields as described in the question. This junction is necessary, as we can have more than an equal date for both the minimum value and the maximum value. As we can see in the image below, we have three values for May 3rd and two for May 30th:

inserir a descrição da imagem aqui

To the minute start time we would have:

(
  select min(hora_inicio) from minha_tabela
  inner join limites on limites.data_minima = data_inicio
  where codigo = 2
) as hora_minima

To the maximum end time we would have:

(
  select max(hora_fim) from minha_tabela
  inner join limites on limites.data_maxima = data_fim
  where codigo = 2
) as hora_maxima

SQL with the solution complete would look like this:

with limites as (
    select min(data_inicio) data_minima, max(data_fim) data_maxima
    from minha_tabela
    where codigo = 2
)
select (
  select data_minima from limites
) as data_minima,
(
  select data_maxima from limites
) as data_maxima,
(
  select min(hora_inicio) from minha_tabela
  inner join limites on limites.data_minima = data_inicio
  where codigo = 2
) as hora_minima,
(
  select max(hora_fim) from minha_tabela
  inner join limites on limites.data_maxima = data_fim
  where codigo = 2
) as hora_maxima
from dual

Upshot:

inserir a descrição da imagem aqui

1

If I understand the problem, only grouping by code can solve:

select min(data_inicio), max(data_fim), min(hora_inicio), max(hora_fim)
from minha_tabela
where codigo = 2
group by codigo
  • Gypsy, it’s not that simple. The result you posted is the same as the given example, therefore not expected.

  • It is not clear what you want. Note that neither the example you put makes sense. In the second record (first photo) the final date is April 19. Do you want a record only with the lowest initial date and time and the highest final date and time, or do you want something else?

  • The first image corresponds to the scope or set of records that I should use to check the larger start date, longer end date, shorter start time and longer end time. It only serves to illustrate the researched universe. Therefore, it does not need to be ordered.

  • I made an adjustment to the question to improve understanding.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.