2016-04-04 2 views
0

Je cherche à convertir une colonne de base de données Oracle qui détient des secondes (durée de la musique) au format ISO 8601 pour la durée. Mais j'ai cherché partout une procédure Oracle ou un morceau de SQL qui le fait sans succès. Je vois qu'il y a des exemples dans d'autres langages mais pas Oracle SQL ni PL/SQL.Convertir la valeur secondes au format ISO 8601 pour la durée dans Oracle SQL

Voici quelques informations sur the ISO standard.

Je suis sur une base de données Oracle 11g.

+0

Pouvez-vous donner un échantillon valeur de durée et le résultat que vous attendez? Et la gamme que vous attendez - la durée peut-elle dépasser une heure, par exemple? –

+0

Oui, de nombreuses compositions de Beethoven ou de Mazart durent plus d'une heure. –

Répondre

0

Oracle a un type de données d'intervalle dans lequel vous pouvez convertir votre durée, mais vous ne pouvez pas vraiment le formater. Le plus simple est de le décomposer en utilisant mod et trunc pour diviser la valeur en heures et minutes complètes, et en secondes restantes.

avec des données de l'échantillon:

with t (duration) as (
    select 59 from dual 
    union all select 60 from dual 
    union all select 61 from dual 
    union all select 3599 from dual 
    union all select 3600 from dual 
    union all select 86399 from dual 
) 
select duration, 
    numtodsinterval(duration, 'SECOND') as interval_value, 
    'PT' 
    || case when trunc(duration/3600) > 0 then trunc(duration/3600) || 'H' end 
    || case when trunc(duration/3600) > 0 or trunc(mod(duration, 3600)/60) > 0 
     then trunc(mod(duration, 3600)/60) || 'M' end 
    || trunc(mod(duration, 60)) || 'S' as iso_value 
from t; 

    DURATION INTERVAL_VAL ISO_VALUE 
---------- ------------ ------------ 
     59 0 0:0:59.0 PT59S  
     60 0 0:1:0.0 PT1M0S  
     61 0 0:1:1.0 PT1M1S  
     3599 0 0:59:59.0 PT59M59S  
     3600 0 1:0:0.0 PT1H0M0S  
    86399 0 23:59:59.0 PT23H59M59S 

Je suppose que la durée ne peut jamais dépasser 24 heures, et que vous voulez que quelques secondes entières; mais des durées plus longues et une plus grande précision peuvent être gérées si nécessaire.

Je suppose également que vous voulez exclure la partie optionnelle la plus haute, donc vous ne montreriez pas 0H; mais cela ayant montré des heures que vous voulez montrer minutes et secondes même si elles sont nulles. Vous pouvez modifier (ou supprimer) les instructions de cas si ce n'est pas le cas.

Pour afficher toujours les trois parties:

select duration, 
    numtodsinterval(duration, 'SECOND') as interval_value, 
    'PT' || trunc(duration/3600) || 'H' 
    || trunc(mod(duration, 3600)/60) || 'M' 
    || trunc(mod(duration, 60)) || 'S' as iso_value 
from t; 

    DURATION INTERVAL_VAL ISO_VALUE 
---------- ------------ ------------ 
     59 0 0:0:59.0 PT0H0M59S 
     60 0 0:1:0.0 PT0H1M0S  
     61 0 0:1:1.0 PT0H1M1S  
     3599 0 0:59:59.0 PT0H59M59S 
     3600 0 1:0:0.0 PT1H0M0S  
    86399 0 23:59:59.0 PT23H59M59S 

Pour Ne jamais afficher zéro parties:

select duration, 
    numtodsinterval(duration, 'SECOND') as interval_value, 
    'PT' 
    || case when trunc(duration/3600) > 0 then trunc(duration/3600) || 'H' end 
    || case when trunc(mod(duration, 3600)/60) > 0 then trunc(mod(duration, 3600)/60) || 'M' end 
    || case when trunc(mod(duration, 60)) > 0 then trunc(mod(duration, 60)) || 'S' end 
    as iso_value 
from t; 

    DURATION INTERVAL_VAL ISO_VALUE 
---------- ------------ ------------ 
     59 0 0:0:59.0 PT59S  
     60 0 0:1:0.0 PT1M   
     61 0 0:1:1.0 PT1M1S  
     3599 0 0:59:59.0 PT59M59S  
     3600 0 1:0:0.0 PT1H   
    86399 0 23:59:59.0 PT23H59M59S 
+0

Encore une fois, M. Alex Poole le fait à nouveau, c'est fantastique, je suis allé avec la partie ne jamais montrer zéro et fonctionne comme un rêve. Merci :-) tu as fait ma journée. –

+0

@ShaunKinnair - L'approche d'extraction de Wernfried obtient le même résultat que ma dernière requête, sans éléments zéro, et est un peu plus propre - au moins une fois que vous avez converti votre valeur numérique en un intervalle. Je viens de me rendre compte que ni l'un ni l'autre ne traitent d'une durée de zéro comme l'article auquel vous avez lié le dit; ma deuxième requête serait, mais pour l'un des autres, vous auriez besoin de gérer cela. –

1

Vous pouvez également utiliser la fonction EXTRACT:

WITH t AS (
    SELECT INTERVAL '59' SECOND AS duration FROM dual 
    UNION ALL SELECT INTERVAL '60' SECOND FROM dual 
    UNION ALL SELECT INTERVAL '61' SECOND FROM dual 
    UNION ALL SELECT INTERVAL '3599' SECOND FROM dual 
    UNION ALL SELECT INTERVAL '3600' SECOND FROM dual 
    UNION ALL SELECT INTERVAL '86399' SECOND FROM dual 
) 
SELECT duration, 
    'PT' 
     ||NULLIF(EXTRACT(HOUR FROM duration)||'H', '0H') 
     ||NULLIF(EXTRACT(MINUTE FROM duration)||'M', '0M') 
     ||NULLIF(EXTRACT(SECOND FROM duration)||'S', '0S') 
    AS iso_value 
FROM t; 
+0

Il est peut-être utile de mentionner qu'ils doivent faire 'numtodsinterval (duration, 'SECOND')' pour convertir le nombre initial de secondes en un intervalle. –

+0

'INTERVAL '59' SECOND AS duration 'renvoie un type de données' INTERVAL'. –

+0

Bien sûr, mais l'OP commence avec des nombres dans la colonne de durée, pas un intervalle. –