如何在 Presto 中将小时解析为人类可读的字符串? (十进制到时间)

How to parse hours into human readable string in Presto? (decimal to time)

我是运行以下

SELECT A, B, AVG(date_diff('hour', creation_date,current_timestamp)) as AVG_in_hours FROM table GROUP BY A,B

这给了我:

A   B   AVG_in_hours
1   2   1587.25
1   3  159.43283582089552
1   4  1

我希望它是:

A   B   AVG_in_hours                    AVG_TEXT
1   2   1587.25                66 days, 3 hours, 15 minutes
1   3  159.43283582089552      6 days, 15 hours, 25 minutes
1   4  1                       1 hours, 0 minutes

基本上是将十进制的AVG_in_hours转换成可读的字符串。 我只需要天数、小时数和分钟数。

如何快速完成此操作?

试试这个代码。我没有测试它:

with raw_data as (
SELECT A, B, AVG(date_diff('hour', creation_date,current_timestamp)) as AVG_in_hours,
AVG(date_diff('day', creation_date,current_timestamp)) as days,
AVG(date_diff('hour', creation_date,current_timestamp))- 
    AVG(date_diff('day', creation_date,current_timestamp))*24 as hrs,
AVG(date_diff('minute', creation_date,current_timestamp))- 
    AVG(date_diff('hour', creation_date,current_timestamp))*60 as minutes
FROM table
GROUP BY A,B
)

select a,b, AVG_in_hours, 
(case 
when round(days)=0 then cast(round(days) as varchar) || ' days, ' 
else '' end)
|| cast(round(hrs) as varchar) || ' hours, ' || cast(round(minutes) as varchar) || ' minutes' as AVG_TEXT
from raw_data

您可以试试下面的代码。为您的数据库稍微更改它,因为它是为 SQL_Server 编写的。逻辑基本上是检查 avg_in_minutes 的值,如果它超过 1440 分钟(等于 1 天)或超过 60 分钟(等于一小时),然后使用计算来扣除天数,小时,剩下的是分钟。

WITH test (A, B, insert_date) AS
     (SELECT 1, 2 , '2020-05-01' UNION 
      SELECT 1, 2 , '2020-05-02' UNION
      SELECT 1, 2 , '2020-05-12' UNION
      SELECT 1, 3 , '2020-05-01' UNION
      SELECT 1, 3 , '2020-05-10' UNION
      SELECT 1, 4 , '2020-05-01' UNION
      SELECT 1, 5 , '2020-05-03'
     )

SELECT *,
CASE WHEN AVG_in_minutes > 1440
     THEN CAST((AVG_in_minutes - (AVG_in_minutes % 1440))/1440 AS VARCHAR) + ' days, '
        + CAST(((AVG_in_minutes%1440 - (AVG_in_minutes%1440)%60)/60) AS VARCHAR) + ' hours, '
        + CAST(((AVG_in_minutes%1440)%60) AS VARCHAR) + ' minutes'
     WHEN AVG_in_minutes > 60
     THEN CAST(((AVG_in_minutes%1440 - (AVG_in_minutes%1440)%60)/60) AS VARCHAR) + ' hours, '
        + CAST(((AVG_in_minutes%1440)%60) AS VARCHAR) + ' minutes'
     ELSE CAST(((AVG_in_minutes%1440)%60) AS VARCHAR) + ' minutes'
     END AS AVG_in_Text
FROM
(
SELECT A, B, 
AVG(datediff(MINUTE, insert_date,current_timestamp)) AS AVG_in_minutes
from test
GROUP BY A,B
) test_final