web-dev-qa-db-fra.com

Comment comparer deux valeurs DATE basées uniquement sur une partie de date dans Oracle?

J'essaie d'obtenir des comptes pour les 30 derniers jours avec la requête suivante -

SELECT date_occured, COUNT(*) FROM problem
WHERE date_occured >= (CURRENT_DATE - 30)
GROUP BY date_occured;

//date_occured field is of type DATE.

Essentiellement, dans ma requête, j'essaie de comparer uniquement la partie date dans la condition date_occured >= (CURRENT_DATE - 30), mais elle semble également comparer l'heure.

J'ai essayé le TRUNC comme suit -

TRUNC(date_occured) >= TRUNC(CURRENT_DATE - 30)

Mais quand la requête est exécutée, elle ne retourne jamais.

J'ai aussi essayé -

SELECT date_occured, COUNT(*) FROM problem    
GROUP BY date_occured
HAVING TRUNC(date_occured) >= TRUNC(CURRENT_DATE - 30);

Encore une fois, il ne revient jamais.

Comment comparer uniquement les éléments de date de deux valeurs DATE dans Oracle?

11
Bhesh Gurung

Pour cette condition, il suffit de TRONCER le côté droit:

WHERE date_occured >= TRUNC(CURRENT_DATE - 30)

Pourquoi? Parce que si TRUNC (date_occured) est postérieur à TRUNC (CURRENT_DATE - 30), tout moment après TRUNC (date_occured) sera nécessairement postérieur à TRUNC (CURRENT_DATE - 30). 

Il est évidemment toujours vrai que date_occured> = TRUNC (date_occured) (pensez-y).

La logique dit que si A> = B et B> = C, il s'ensuit que A> = C

Maintenant, remplacez:

  • A: date_occured 
  • B: TRUNC (date_occured)
  • C: TRUNC (CURRENT_DATE - 30)
15
Tony Andrews

Je pense que vous voudrez également tronquer la partie sélectionnée:

 SELECT TRUNC(date_occured) AS short_date_occured, COUNT(*)
 FROM problem 
 WHERE date_occured >= trunc(SYSDATE- 30) 
 GROUP BY short_date_occured;
3
Lost in Alabama

J'aurais tendance à penser que Tony a raison et que vous ne voulez vraiment que TRUNC la partie droite de l'expression.

Si vous souhaitez TRUNC les deux côtés de l'expression et que vous rencontrez des problèmes de performances, vous avez probablement besoin d'un index basé sur une fonction.

CREATE INDEX idx_problem_trunc_dt_occured
    ON problem( trunc( date_occurred ) );

Cela permettrait à votre requête d'origine d'utiliser l'index basé sur la fonction.

1
Justin Cave

Essayez d’utiliser SYSDATE vs CURRENT_DATE. Sysdate utilise l'heure locale du serveur où CURRENT_DATE renvoie la date et l'heure actuelles du serveur dans l'heure locale de la connexion du client.

1
northpole

Voici l'approche favorable à l'index.

vous n'avez pas besoin d'utiliser les fonctions sur les colonnes si vous utilisez la fonction Native MONTHS_BETWEEN d'Oracle.

Il retourne la différence en nombre de mois. Les jours sont également donnés en différence mais du côté de la précision, c'est pourquoi j'ai préféré utiliser la clause BETWEEN

WHERE MONTHS_BETWEEN(date_occured, CURRENT_DATE - 30) BETWEEN 0 AND 1
0
Simonare