How to determine largest resolution of an INTERVAL?

廉价感情. 提交于 2019-12-24 11:41:11

问题


How can I determine the largest resolution of an INTERVAL value? For example:

  • INTERVAL '100 days and 3 seconds' => day
  • TIME '20:05' - TIME '12:01:01' => hour
  • AGE(NOW(), NOW() - INTERVAL '1 MONTH') => month

回答1:


The question isn't 100% clear so the answer may or may not be exactly what you're looking for, but...

There is a justify_interval() function, which you might want to look into.

test=# select justify_interval(INTERVAL '100 days 3 seconds');
    justify_interval     
-------------------------
 3 mons 10 days 00:00:03
(1 row)

test=# select justify_interval(TIME '20:05' - TIME '12:01:01');
 justify_interval 
------------------
 08:03:59
(1 row)

test=# select justify_interval(AGE(NOW(), NOW() - INTERVAL '1 MONTH'));
 justify_interval 
------------------
 1 mon
(1 row)

For there extract the year, then month, then day, etc. until you come up with a non-zero answer:

test=# select extract('mon' from interval '3 mons 10 days 00:00:03');
 date_part 
-----------
         3

Re your other question in comments:

create function max_res(interval) returns interval as $$
select case
       when extract('year' from justify_interval($1)) > 0 or
            extract('mon' from justify_interval($1)) > 0 or
            extract('day' from justify_interval($1)) > 0
       then '1 day'
       when extract('hour' from justify_interval($1)) > 0
       then '1 hour'
       when ...
       end;
$$ language sql immutable strict;



回答2:


INTERVAL is 12 bytes and is a struct containing months, days and microseconds and has a range of +/- 178000000 years. It always has a fixed max size of 178000000 years due to the way that it stores this information.

Be careful with your understanding of "a month" because the Julian month is not a constant in the same way that an hour or a minute is (e.g. how many days are in the month of February? Or how many days are there in a year? It's not always 30 or 365 in reality and PostgreSQL updates things correctly. per an interesting conversation on IRC, Adding 1 month::INTERVAL to January 30th will result in whatever the last day of February because it increments the tm_mon member of struct tm (and in this case, rolls back to the previous valid date).


Ah ha! I get the question now (or at least I think so). You're looking to determine the largest "non-zero integer unit" for a given INTERVAL.

PostgreSQL doesn't have a built-in function that returns that information. I think you're going to have to chain a conditional and return type. Some example PL code:

t := EXTRACT(EPOCH FROM my_time_input);
IF t >= 31104000 THEN
  RETURN 'year';
ELSIF t >= 2592000 THEN
  RETURN 'month';
ELSIF t >= 604800 THEN
  RETURN 'week';
ELSIF t >= 86400 THEN
  RETURN 'day';
ELSIF t >= 3600 THEN
  RETURN 'hour';
ELSIF t >= 60 THEN
  RETURN 'minute'
ELSIF t > 1 THEN
  RETURN 'seconds';
ELSIF t == 1 THEN
  RETURN 'second';
ELSE
  RETURN resolve_largest_sub_second_unit(my_time);
END IF;


来源:https://stackoverflow.com/questions/6374453/how-to-determine-largest-resolution-of-an-interval

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!