【问题标题】:Converting Minutes Column to Days, Hours and Minutes SQL将分钟列转换为天、小时和分钟 SQL
【发布时间】:2020-08-07 22:31:47
【问题描述】:

我有一个这样的专栏 -

XXX_2019
234
2142
1423
4634
7886
3143
3243

我要输出

XXX_2019
3 hours, 54 minutes
1 days, 11 hours, 42 minutes
23 hours, 43 minutes

这不是日期时间。这只是一个分钟专栏。我正在使用 Vertica。

【问题讨论】:

    标签: sql vertica


    【解决方案1】:

    您可以直接执行此操作。像这样的:

    select trim(leading ', ' from
         (case when XXX_2019 > 24*60 then ', ' || floor(xxx_2019 / (24*60)) || ' days' else '' end) ||
         (case when XXX_2019 > 60 then ', ' || floor((xxx_2019 % (24*60)) / 60) || ' hours' else '' end) ||
         (', ' || xxx_2019 % 60 || ' minutes')
        )
    from (values (12345), (123), (12)) v(xxx_2019);
    

    Here 是一个 dbfiddle(使用 Postgres)。

    【讨论】:

    • 谢谢!我试过了,但它在 else 附近给了我一个语法错误,所以我删除了 else,然后它给了我一个接近 end 的语法错误。
    • 我在结束后添加了另一个 ) 但这也没有帮助
    • @CHATSHD 。 . .现在可以了。我添加了一个 dbfiddle 来验证。
    • 非常感谢!有效 !但它看起来像这样 - '2 天,6 小时,7.15760803119019 分钟' 知道为什么吗?
    • @CHATSHD 。 . .这很奇怪。也许XXX_2019 有一个小数部分。运算符% 是模运算符,如果两个参数都是整数,则返回一个整数。
    【解决方案2】:

    让 Vertica 为您完成繁重的工作。

    从分钟计数中提取一个区间,然后从区间中提取日、小时和分钟,并将它们转换为逗号、计数器和单位,连接所有,并删除初始逗号:

    WITH 
    -- your input
    input( xxx_2019 ) AS (
              SELECT  234
    UNION ALL SELECT 2142
    UNION ALL SELECT 1423
    UNION ALL SELECT 4634
    UNION ALL SELECT 7886
    UNION ALL SELECT 3143
    UNION ALL SELECT 3243
    )
    

    -- 从分钟数中得出一个间隔

    ,
    with_interval AS (
      SELECT 
        xxx_2019 
      , (xxx_2019::char(8)||' minutes')::INTERVAL as dircast
      FROM input
    )
    

    --最后,从区间中提取位,并格式化

    SELECT 
      dircast
    , REGEXP_REPLACE(
          CASE EXTRACT(DAY    FROM dircast) 
            WHEN 0 THEN ''
            ELSE ', '||EXTRACT(DAY  FROM dircast)::VARCHAR(5)||' days'
          END
        || CASE EXTRACT(HOUR   FROM dircast) 
            WHEN 0 THEN ''
            ELSE ', '||EXTRACT(HOUR FROM dircast)::VARCHAR(5)||' hours'
          END
        || CASE EXTRACT(MIN   FROM dircast) 
            WHEN 0 THEN ''
            ELSE ', '||EXTRACT(MIN FROM dircast)::VARCHAR(5)||' minutes'
          END
      , '^, ','') AS s
    FROM with_interval
    -- out  dircast |              s               
    -- out ---------+------------------------------
    -- out  03:54   | 3 hours, 54 minutes
    -- out  1 11:42 | 1 days, 11 hours, 42 minutes
    -- out  23:43   | 23 hours, 43 minutes
    -- out  3 05:14 | 3 days, 5 hours, 14 minutes
    -- out  5 11:26 | 5 days, 11 hours, 26 minutes
    -- out  2 04:23 | 2 days, 4 hours, 23 minutes
    -- out  2 06:03 | 2 days, 6 hours, 3 minutes
    
    

    当然也可以直接,例如:

    EXTRACT(DAY    FROM (xxx_2019::char(8)||' minutes')::INTERVAL) 
    

    但我发现它的另一种方式更具可读性......

    当然,您可以使用 @Gordon Linoff 的方法,但我会在 Vertica 中使用整数除法运算符,即双斜线 //,而不是 FLOOR()-ing之后的除法 - 只是为了保持在整数运算范围内,这比浮点运算要快得多。让我迂腐的头脑感到不安的是 INTEGER 隐含地转换为字符,然后将其与字符串连接......

    SELECT
      TRIM(LEADING ', ' FROM
         CASE
           WHEN XXX_2019 > 24*60
           THEN ', ' || ( XXX_2019 // (24*60) )::VARCHAR(5)|| ' days'
           ELSE ''
         END
       ||CASE
           WHEN XXX_2019 > 60
           THEN ', ' || ( (XXX_2019 % (24*60)) // 60 )::VARCHAR(5)|| ' hours'
           ELSE ''
         END
       ||', ' || (xxx_2019 % 60) ::VARCHAR(5)|| ' minutes'
      )                                                                         
    FROM input;
    

    【讨论】:

    • 感谢您回复此主题。我不明白您解决方案的第一部分,因为 XXX_2019 有很多价值。您对 Linoff 方法的修改版本效果很好,但仍然在几分钟内给了我一些额外的价值。知道为什么吗?例如:2 天 6 小时 7.157 分钟
    • 通过在我的问题的第 2 部分将 varchar 更改为 2 来解决问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 2019-02-22
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-05
    相关资源
    最近更新 更多