Mysql
 sql >> Base de données >  >> RDS >> Mysql

Format de date et clarification de la requête SQL

Cela fait beaucoup de questions pour un fil .. mais je vais essayer de répondre à la plupart d'entre elles. (La première question à laquelle vous pouvez répondre vous-même, juste en l'essayant;-)

En ce qui concerne la requête, même si elle s'est exécutée sans erreur, elle peut être améliorée. Je ne vais pas réécrire la requête pour vous, mais voici les principaux problèmes

  • D'abord, jamais utiliser les valeurs client brutes directement dans SQL. Utilisez toujours cfqueryparam pour se protéger contre l'injection sql. Il présente également d'autres avantages, mais celui-ci est essentiel dans une application Web.

  • Deuxièmement, vous transmettez des chaînes de date . Les chaînes de date sont ambiguës et peuvent être mal interprétées, selon le format et l'outil effectuant l'analyse. Il est bien mieux d'utiliser des objets de date Au lieu. Une façon de le faire est d'utiliser cfqueryparam et l'un des types de date :cf_sql_date (date uniquement) ou cf_sql_timestamp (date et l'heure).

  • Troisièmement, comme je l'ai mentionné sur votre autre fil , vous avez vraiment besoin de simplifier votre requête ! Ce nombre de sous-requêtes est déjà difficile à manier. L'ajout de filtres de date à chaque sous-requête la rend carrément ingérable. Je recommanderais de chercher des moyens de le simplifier. Suggestion d'Ed offrait une possibilité, en la réduisant à un seul JOIN et quelques appels de fonction.

Eh bien, en fait, c'est exactement ce que votre IDE affiche cela aux humains. Ce n'est pas vraiment stocké de cette façon. En interne, les dates sont stockées sous forme de grands nombres. Cependant, votre requête doit tenir compte du fait que votre colonne stocke une date et temps.

Supposons que vous vouliez récupérer tous les enregistrements datés en juin :

    form.startDate = "06/01/2013"
    form.endDate = "06/30/2013"

Conceptuellement, vous auriez besoin d'une expression sql comme celle-ci :

    WHERE column BETWEEN '06/01/2013 at midnight' AND '06/30/2013 11:59:59 PM' 

Cependant, la construction de ces valeurs de date/heure est un peu maladroite IMO. Une façon plus simple de le gérer consiste à utiliser ce paradigme :

   WHERE column >= {startDateAtMidnight}        
   AND   column <  {dayAfterEndDateAtMidnight}

Votre filtre de requête réel ressemblerait à ceci :

    WHERE column >= <cfqueryparam value="#form.startDate#" 
                                  cfsqltype="cf_sql_date">
    AND   column <  <cfqueryparam value="#dateAdd('d', 1, form.endDate)#" 
                                  cfsqltype="cf_sql_date">

En ajoutant un jour à form.endDate , et en utilisant un < comparaison, la requête résultante est :

    WHERE column >= '2013-06-01 00:00:00'  
    AND   column < '2013-07-01 00:00:00'  

Cela produira exactement les mêmes résultats que l'expression BETWEEN précédente.