Ma requête est la suivante:
select * from session ses inner join event evt on ses.evt_id = ses.id inner join application app on app.id = ses.app_id where app.id = 9999 and ses.usernumber = 69 and to_char(ses_date, 'dd.MM.yyyy HH24:MI:SS') between '22.10.2015 23:59:59' and '23.10.2015 23:59:59'
Désormais, les premiers résultats datent bien du 23.10.2015 mais il y en a aussi peu du 23.06.2014 .
Comment est-ce possible?
3 Réponses :
Pourquoi convertir cette date en chaîne en premier lieu? C'est inefficace et dangereux. Au lieu de cela, vous pouvez filtrer la colonne directement par rapport aux dates ou aux horodatages littéraux.
Je suppose que vous voulez:
ses_date between to_date('22.10.2015T23:59:59', 'dd.mm.yyyy"T"hh24:mi:ss') and to_date('23.10.2015T23:59:59', 'dd.mm.yyyy"T"hh24:mi:ss')
Cela amène des dates dont la portion journalière est 2015, 22 ou 23 octobre.
Bien sûr, vous pouvez également utiliser des horodatages littéraux si vous le souhaitez. Si vous souhaitez reproduire la logique de votre code d'origine:
ses_date >= timestamp '2015-10-22 23:59:59' and ses_date <= timestamp '2015-10-23 23:59:59'
Si vous recevez les paramètres de date sous forme de chaînes en premier lieu, convertissez-les en dates:
ses_date >= date '2015-10-22' and ses_date < date '2015-10-24'
J'ai besoin d'utiliser des chaînes, car j'analyse la date à partir d'une URL à laquelle un utilisateur tape "& start = 22.10.2015T23: 59: 59 & end = 23.10.2020T23: 59: 59"
@willberthos: puis convertissez les chaînes en date. Voir ma mise à jour.
Je pense que c'est la bonne réponse, mais comme j'utilise JPQL, je ne peux pas utiliser la fonction to_date. Je n'ai pas encore trouvé le moyen de convertir String au bon format JPQL, à partir duquel j'ai posé une question distincte: stackoverflow.com/questions/64857100/...
@willberthos: pourquoi pas simplement: ses_date between to_date(?1, 'dd.mm.yyyy"T"hh24:mi:ss') and to_date(?2, 'dd.mm.yyyy"T"hh24:mi:ss')
car JPQL n'a pas de fonction "to_date"
Comment est-ce possible?
Vous utilisez
TO_CHAR
sur un type de données date pour le convertir en type de données chaîne, puis le filtre est:AND ses_date >= DATE '2015-10-23' AND ses_date < DATE '2015-10-24'Ainsi, l'analyseur SQL effectue une comparaison alphanumérique des valeurs et la limite inférieure commence le
22
et le23.06.2014
est supérieure car les premiers caractères de la chaîne sont identiques, puis le deuxième caractère est comparé et2
<3
donc'22.10.2015 23:59:59'
<'23.06.2014'
par rapport à une chaîne. De même, la limite supérieure commence par23.1
et les 3 premiers caractères sont les mêmes, puis0
<1
pour le 4ème caractère donc'23.06.2014'
<'23.10.2015 23:59:59'
(encore une fois, par rapport à une chaîne ). Ainsi, le filtre renvoie true car la valeur de la chaîne se situe entre les limites supérieure et inférieure.Comment résoudre ceci:
Ne comparez pas les valeurs sous forme de chaînes; comparez-les comme des dates.
AND ses_date BETWEEN TO_DATE( '22.10.2015 23:59:59', 'DD.MM.YYYY HH24:MI:SS' ) AND TO_DATE( '23.10.2015 23:59:59', 'DD.MM.YYYY HH24:MI:SS' )ou
AND ses_date BETWEEN TIMESTAMP '2015-10-22 23:59:59' AND TIMESTAMP '2015-10-23 23:59:59'ou
AND ses_date BETWEEN DATE '2015-10-22' + INTERVAL '23:59:59' HOUR TO SECOND AND DATE '2015-10-23' + INTERVAL '23:59:59' HOUR TO SECOND(Remarque: ceux-ci
2015-10-22 23:59:59
valeurs à partir du2015-10-22 23:59:59
.)Si vous ne voulez que des valeurs à tout moment sur le
2015-10-23
alors:{string value} BETWEEN {string value} AND {string value}
Vous vous attendez à ce que vos valeurs soient évaluées comme des dates, où la composante année est la plus importante, qui se trouve à la fin de votre description de date. Cependant, étant donné que vous convertissez vos dates en chaînes, elles sont évaluées par ordre alphabétique, ce qui signifie que dans la comparaison, la première différence (de gauche à droite) décide du résultat. Alphabétiquement
22.10.2015 23:59:59 <23.06.2014 <23.10.2015 23:59:59
est vrai.
Les trois chaînes commencent par un «2». Le premier continue avec un autre «2», tandis que le second continue avec un «3». Le premier est donc plus petit que le second. Le troisième continue avec un «3», tout comme le second. Le deuxième et le troisième continuent avec un «.». Et maintenant vient la différence: le premier continue avec «0» et le troisième continue avec un «1». Même si ces chaînes représentent des dates pour vous et que la composante année du troisième est plus petite que la seconde, en tant que chaînes, la seconde est plus petite que la troisième.
Plusieurs approches peuvent être utilisées.
Fondamentalement, si vous ne convertissez pas vos dates en chaîne, mais vos entrées to_date
, comme @GMB l'a décrit, cela devrait fonctionner correctement.
Même si la première approche devrait fonctionner hors de la boîte et est une solution parfaitement faisable, si, pour une raison quelconque, ce n'est pas une option (par exemple, les dates dans l'URL peuvent être mal formées en raison de recherches d'utilisateurs), alors vous voudrez peut-être utiliser le format aaaa.mm.jj dans votre URL et utilisez ce format dans vos conversions to_char
. L'idée sous-jacente est que si le composant année vient en premier, suivi du mois puis du composant de date, la comparaison entre deux valeurs aura des résultats similaires, indépendamment du fait que vous compariez les valeurs sous forme de dates ou de chaînes.
La comparaison de chaînes de caractères fonctionne de cette façon. Passez au type de données d'horodatage approprié, ou au moins au format ANSI / ISO «2015-10-22 23:59:59».