2010-03-03 7 views
46

J'utilise la base de données Oracle. Je veux exécuter une requête pour vérifier les données entre deux dates.Oracle date "Entre" requête

NAME    START_DATE  
------------- ------------- 
Small Widget  15-JAN-10 04.25.32.000000 PM  
Product 1   17-JAN-10 04.31.32.000000 PM 



select * from <TABLENAME> where start_date 
BETWEEN '15-JAN-10' AND '17-JAN-10' 

Mais je n'obtiens aucun résultat de la requête ci-dessus. Je pense que je dois utiliser "j'aime" et "%". Mais je ne sais pas où les utiliser. S'il vous plaît jeter quelques lumières à ce sujet.

merci d'avance.

Répondre

74

A en juger par votre sortie, il semble que vous avez START_DATE défini comme horodatage. Si c'était une date régulière Oracle serait capable de gérer la conversion implicite. Mais comme ce n'est pas le cas, vous devez explicitement transformer ces chaînes en dates.

SQL> alter session set nls_date_format = 'dd-mon-yyyy hh24:mi:ss' 
    2/

Session altered. 

SQL> 
SQL> select * from t23 
    2 where start_date between '15-JAN-10' and '17-JAN-10' 
    3/

no rows selected 

SQL> select * from t23 
    2 where start_date between to_date('15-JAN-10') and to_date('17-JAN-10') 
    3/

WIDGET       START_DATE 
------------------------------ ---------------------- 
Small Widget     15-JAN-10 04.25.32.000  

SQL> 

Mais nous n'avons toujours qu'une ligne. C'est parce que START_DATE a un élément de temps. Si nous ne spécifions pas le composant heure, Oracle le met par défaut à minuit. C'est très bien pour le de côté de la BETWEEN mais pas pour le jusqu'à côté:

SQL> select * from t23 
    2 where start_date between to_date('15-JAN-10') 
    3      and to_date('17-JAN-10 23:59:59') 
    4/

WIDGET       START_DATE 
------------------------------ ---------------------- 
Small Widget     15-JAN-10 04.25.32.000 
Product 1      17-JAN-10 04.31.32.000 

SQL> 

modifier

Si vous ne pouvez pas passer dans le composant de temps il y a deux choix. La première consiste à modifier la clause WHERE pour supprimer l'élément de temps de critères:

where trunc(start_date) between to_date('15-JAN-10') 
          and to_date('17-JAN-10') 

Cela pourrait avoir un impact sur les performances, car il disqualifie tout indice b-tree sur START_DATE. Vous auriez besoin de construire un index basé sur la fonction à la place.

vous pourriez aussi ajouter l'élément de temps à la date dans votre code:

where start_date between to_date('15-JAN-10') 
        and to_date('17-JAN-10') + (86399/86400) 

En raison de ces problèmes que beaucoup de gens préfèrent éviter l'utilisation de between en vérifiant les limites de date comme celle-ci:

where start_date >= to_date('15-JAN-10') 
and start_date < to_date('18-JAN-10') 
+0

Je ne peux pas passer l'heure seule date. –

+0

wow ça marche bien APC ... merci beaucoup pour votre support –

+0

@APC a fonctionné comme charme dans ORACLE 11 G – Alex

20

Vous devez convertir ceux dates réelles au lieu de chaînes, essayez ceci:

SELECT * 
FROM <TABLENAME> 
WHERE start_date BETWEEN TO_DATE('2010-01-15','YYYY-MM-DD') AND TO_DATE('2010-01-17', 'YYYY-MM-DD'); 

Edité pour traiter format spécifié:

SELECT * 
FROM <TABLENAME> 
WHERE start_date BETWEEN TO_DATE('15-JAN-10','DD-MON-YY') AND TO_DATE('17-JAN-10','DD-MON-YY'); 
+0

Merci pour votre réponse rapide. Mais je reçois les dates From et To du fichier d'action dans ce format "17-JAN-10". Donc, comme ceci: SELECT \t * FROM uson_assetaccess WHERE accessdate ENTRE TO_DATE ('17 -FEB-10 ',' jj-MMM-aa ') ET TO_DATE ('17 -FEB-10', 'jj-MMM- yy '); Mais j'ai eu une erreur: ORA-01821: format de date non reconnu –

+0

Il suffit d'utiliser des spécificateurs de format différents, remplacer le "MMM" par "MON", voir mon édition. –

+0

Merci encore pour la réponse immédiate. Mais j'ai utilisé cette requête Mais maintenant l'erreur de format date est partie. maintenant je n'ai aucune donnée trouvée erreur même les données sont là dans la table. Je pense que dans la table date est là avec le temps mais nous envoyons avec la date seulement. Est-ce à cause de cette raison? S'il vous plaît clarifier –

3

Comme APC l'a fait remarquer à juste titre, votre colonne start_date semble être un TIMESTAMP, mais il peut aussi s'agir d'un type de données TIMESTAMP WITH LOCAL TIMEZONE ou TIMESTAMP WITH TIMEZONE. Ceux-ci pourraient bien influencer toutes les requêtes que vous faisiez sur les données si votre serveur de base de données était dans un fuseau horaire différent de vous. Cependant, gardons cela simple et supposons que vous êtes dans le même fuseau horaire que votre serveur. Tout d'abord, pour vous donner la confiance, vérifiez que start_date est un type de données TIMESTAMP.

Utilisez la commande SQLPlus DESCRIBE (ou l'équivalent dans votre IDE) pour vérifier que cette colonne est un type de données TIMESTAMP.

par exemple

DESCRIBE matable

devrait signaler:

Name  Null? Type 
----------- ----- ------------ 
NAME    VARHAR2(20) 
START_DATE  TIMESTAMP 

S'il est rapporté comme type = TIMESTAMP alors vous pouvez interroger vos plages de dates avec la conversion de la date de TO_TIMESTAMP simple, qui exige aucun argument (ou image).

Nous utilisons TO_TIMESTAMP pour nous assurer que tout index de la colonne START_DATE est pris en compte par l'optimiseur. La réponse d'APC a également noté qu'un index basé sur la fonction aurait pu être créé sur cette colonne et que cela influencerait le prédicat SQL mais nous ne pouvons pas commenter cela dans cette requête. Si vous voulez savoir comment savoir quels index ont été appliqués à la table, postez une autre question et nous pourrons y répondre séparément.

Donc, en supposant qu'il existe un index sur start_date, qui est un type de données TIMESTAMP et que vous voulez l'optimiseur de le considérer, votre SQL serait:

select * from mytable where start_date between to_timestamp('15-JAN-10') AND to_timestamp('17-JAN-10')+.9999999 

+.999999999 est très proche mais ISN » Tout à fait 1 donc la conversion du 17-JAN-10 sera aussi proche de minuit ce jour-là que possible, donc la requête renvoie les deux lignes.

La base de données verra BETWEEN à partir 15-janv.-10: 00: 00: 00: 0000000 à 17-janv.-10 23: 59: 59: 99999 et comprendra donc toutes les dates du 15, 16 et 17 janvier 2010 quelle que soit la composante temporelle de l'horodatage.

Espérons que ça aide.

Dazzer

1

Date de vente Entre la requête

SELECT * 
    FROM emp 
    WHERE HIREDATE between to_date (to_char(sysdate, 'yyyy') ||'/09/01', 'yyyy/mm/dd') 
    AND to_date (to_char(sysdate, 'yyyy') + 1|| '/08/31', 'yyyy/mm/dd'); 
1

Après requête peut également être utilisé:

select * 
    from t23 
where trunc(start_date) between trunc(to_date('01/15/2010','mm/dd/yyyy')) and trunc(to_date('01/17/2010','mm/dd/yyyy')) 
+2

Si une table est grande et que la colonne date est indexée, vous devriez éviter les expressions, utilisez 'start_date between to_date (' 01/15/2010 ',' mm/jj/aaaa ') et to_date ('01/17/2010', 'mm/jj/aaaa') + 1' à la place. – Dmitry