2017-09-08 2 views
3

SAS, je crée un ensemble de données (dt) avec des dates en utilisant secondes avec 6 décimales fractionnaires:Comment puis-je sélectionner à partir d'une table Oracle avec un horodatage (6)?

data dt; 
    dt_21_aug_2017_23_59_59_999999 = '21aug2017:23:59:59.999999'dt; 
    dt_01_jan_1960_23_59_59_999999 = '01jan1960:23:59:59.999999'dt; 
run; 

Je "format" l'ensemble de données:

data dt_formatted; 
    set dt; 

    format dt_21_aug_2017_23_59_59_999999 datetime32.6; 
    format dt_01_jan_1960_23_59_59_999999 datetime32.6; 
run; 

je peux voir que la 6 chiffres fractionnaires sont conservés.

J'utilise dt_formatted pour créer une table Oracle:

libname tq84_ora oracle 
    user      = &ora_user 
    password     = &ora_password 
    path      = &ora_server 
; 

proc sql; 
    create table tq84_ora.dt_formatted as 
    select * from work .dt_formatted; 
quit; 

la table est créée, si besoin, avec deux colonnes timestamp(6).

Si je passe par pour interroger la table avec une condition where, l'enregistrement inséré est retourné:

proc sql; 
    connect to oracle (
    user = &ora_user 
    pw = &ora_password 
    path = &ora_server 
); 

    select * from connection to oracle (
    select * 
    from dt_formatted 
    where dt_21_aug_2017_23_59_59_999999 = TO_TIMESTAMP(
     '21AUG2017:23:59:59.999999', 
     'DDMONYYYY:HH24:MI:SS.FF', 
     'NLS_DATE_LANGUAGE=American' 
    ) 
); 

    disconnect from oracle; 
quit; 

Toutefois, si j'utilise la méthode traditionnelle pour sélectionner des enregistrements, aucun enregistrement est retourné:

proc sql; 
    select * from tq84_ora.some_dates_date_format 
    where dt_21_aug_2017_23_59_59_999999 = '21aug2017:23:59:59.999999'dt; 
quit; 

Toutefois, si je sélectionne sur dt_01_jan_1960_23_59_59_999999, le dossier est retourné:

proc sql; 
    select * from tq84_ora.some_dates_date_format 
    where dt_01_jan_1960_23_59_59_999999 = '01jan1960:23:59:59.999999'dt; 
quit; 

La raison semble être une limitation avec des points flottants. Encore, c'est étrange puisque Oracle stocke clairement la date de 2017 avec 6 chiffres (qui sont 9). Alors, que puis-je faire pour sélectionner l'enregistrement 2017 avec l'approche traditionnelle proc sql?

+0

est la variable entrée en SAS en tant que valeur datetime? Si vous extrayez l'enregistrement en utilisant la syntaxe SQL passthru lors de votre première étape dans un ensemble de données SAS, pouvez-vous utiliser le littéral datetime pour le sélectionner dans l'ensemble de données SAS? Cela devrait aider à déterminer si le problème réside dans la conversion du littéral DT en nombres réels ou dans l'envoi de la constante datetime dans la base de données distante. – Tom

Répondre

1

Il est possible d'utiliser un LIKE et de prendre la date sous forme de chaîne.

data test; 
    format new_date $50.; 
    set work.entity; 

    new_date=datefrom; 
run; 

proc sql outobs=1; 
    select * from work.test where new_date like '%189%'; 
run; 

datefrom était dans un format de date. new_date réagit en tant que chaîne.

Dans votre cas, vous pouvez faire une instruction select avec la clause where:

proc sql; 
     select * from work.dt_formatted where dt_21_aug_2017_23_59_59_999999 like '%jan2017:%' 
OR dt_21_aug_2017_23_59_59_999999 like '%feb2017:%' 
    ... 
    ; 

run; 
0

Il semble y avoir un bug dans certains formats SAS où il ne peut pas correctement signaler les chiffres à droite de la virgule pour un nombre supérieur à 1 000 000 000. Notez que le format DATETIME fonctionne réellement, mais pas les autres formats SAS comme BEST, F et COMMA. Cela a peut-être un impact sur la façon dont SAS transfère la constante à la base de données distante. Je recommande d'ouvrir un ticket avec le support SAS pour signaler ce problème.

data test; 
    length int frac 8 format $42 str $26 dec $8; 
    frac=0.999999; 
    format int comma15. frac 8.6 ; 
    do int =10**9-1 to 10**9+1 by 1 ; 
    do format='datetime26.6','F26.6','best26.6','comma26.6'; 
     str=putn(int+frac,format); 
     dec=scan(str,-1,'.'); 
     num9s=countc(dec,'9'); 
     output; 
    end; 
    end; 
run; 

enter image description here