2011-05-29 2 views
1

J'ai une requête mysql qui fonctionne bizarrement. Je poste les 2 requêtes avec les données d'entrée changées et les résultats sont listés sous chaque requête.Explique comment fonctionne la requête suivante?

Query 1 (zone à noter BETWEEN '13/05/11' AND '30/05/11'):

 
SELECT COUNT(pos_transaction_id) AS total, 
DATE_FORMAT(pt.timestamp,'%d-%m-%Y %H:%i:%S') AS Date, 
SUM(amount) AS amount 
FROM pos_transactions pt 
WHERE DATE_FORMAT(pt.timestamp,'%e/%m/%y') BETWEEN '13/05/11' AND '30/05/11' 
GROUP BY WEEK(pt.timestamp) ORDER BY pt.timestamp 

sortie:
enter image description here

Query 2 (zone à noter BETWEEN '3/05/11' AND '30/05/11'):

 
SELECT COUNT(pos_transaction_id) AS total, 
DATE_FORMAT(pt.timestamp,'%d-%m-%Y %H:%i:%S') AS Date, 
SUM(amount) AS amount 
FROM pos_transactions pt 
WHERE DATE_FORMAT(pt.timestamp,'%e/%m/%y') BETWEEN '3/05/11' AND '30/05/11' 
GROUP BY WEEK(pt.timestamp) ORDER BY pt.timestamp

sortie:
enter image description here Maintenant, lorsque la plage est augmentée dans la deuxième requête, pourquoi ne reçois-je qu'un seul enregistrement? Et même dans la première requête, je reçois des enregistrements qui sont hors de portée. Qu'est-ce qui va pas avec ça??

EDIT

La requête modifiée ressemble à ceci et encore ne pas faire ce que je voulais faire.

 
SELECT COUNT(pos_transaction_id) AS total, 
DATE_FORMAT(pt.timestamp,'%d-%m-%Y %H:%i:%S') AS Date, 
SUM(amount) AS amount 
FROM pos_transactions pt 
WHERE DATE_FORMAT(pt.timestamp,'%e/%m/%y') BETWEEN STR_TO_DATE('01/05/11','%e/%m/%y') AND STR_TO_DATE('30/05/11','%e/%m/%y') 
GROUP BY WEEK(pt.timestamp) ORDER BY pt.timestamp

La sortie est: enter image description here

Répondre

1

Je pense que vous voyez le résultat de l'intersection de deux mauvaises pratiques.

D'abord, la fonction date_format() renvoie une chaîne. Votre clause WHERE fait une comparaison de chaîne. Dans PostgreSQL

select '26/04/2011' between '13/05/11' AND '30/05/11'; 
-- 
T 

C'est parce que la chaîne '26' est entre les chaînes '13' et '30'. Si vous les écrivez en tant que dates, cependant, PostgreSQL ™ vous dira correctement que '2011-04-26' (suivant le réglage datestyle sur mon serveur) n'est pas dans cette gamme. Deuxièmement, je suppose que les valeurs hors limites inhabituelles apparaissent parce que vous utilisez une expression indéterminée dans votre agrégat. L'expression WEEK(pt.timestamp) n'apparaît pas dans la liste SELECT. Je pense que tous les autres moteurs SQL sur le marché vont jeter une erreur si vous essayez de le faire. Puisque ce n'est pas dans la liste SELECT, MySQL retournera une valeur apparemment aléatoire de cette plage agrégée. Pour éviter ce type d'erreur, ne faites pas de comparaison de chaînes sur les plages de dates ou d'horodatages et n'utilisez pas d'expressions d'agrégat indéterminées.

La publication de DDL et d'instructions SQL INSERT minimales pour reproduire le problème aide les personnes à vous aider.

1

Je suis absolument pas sûr, mais il est peut-être la comparaison se fait comme string et non comme une date.

DATE_FORMAT renvoie string et les deux conditions sont également des chaînes.

Vous devriez essayer sans le DATE_FORMAT, juste la colonne, ou peut-être essayer de convertir la condition à une date.

Je pense quelque chose comme ceci:

pt.timestamp BETWEEN STR_TO_DATE('13/05/11', '%e/%m/%y') AND STR_TO_DATE('30/05/11', '%e/%m/%y') 
+0

vérifier mon édition j'ai encore un problème avec ça .. Avez-vous besoin de quelque chose d'autre à voir ?? – Deepak

1

Je suis assez sûr que vous le vouloir

WHERE pt.timestamp BETWEEN TO_DATE('13/04/11', 'dd/mm/yy') AND TO_DATE('30/05/11', 'dd/mm/yy') 

Avant que vous demandez pour une chaîne entre deux autres chaînes.

Mise à jour

Je pense que quelques-uns qu'ils oublient ici. Basé sur les calculs que vous faites sur pos_transactions.timestamp je vais supposer que c'est un type de timestamp. Dans votre requête, vous devez utiliser l'horodatage directement si vous voulez faire une comparaison de distance. Un horodatage contient déjà toutes les données dont vous avez besoin pour effectuer cette comparaison. Vous n'avez pas besoin de le convertir en jour/mois/année pour le comparer.

Ce que vous devez faire est la suivante:

Trouver toutes les valeurs où mon timestamp se situe entre create a new date from '13/05/11' ET create a new date from '30/05/11'. pt.timestamp est déjà un horodatage, pas besoin de le convertir dans votre clause WHERE.

Ce que vous continuez à faire est de le convertir en une représentation de chaîne. C'est ok quand vous voulez l'afficher, mais pas quand vous voulez le comparer avec d'autres valeurs.

+0

Je ne dois pas appliquer DATE_FORMAT() à l'horodatage ?? – Deepak

+1

la fonction 'TO_DATE' n'existe pas dans MySQL, mais il y en a une' STR_TO_DATE': http://dev.mysql.com/doc/refman/5.0/fr/date-and-time-functions.html#function_str à ce jour @Deepak 'DATE_FORMAT' renvoie une chaîne, je pense que c'est le problème, voir ma réponse. – krtek

+0

je l'ai utilisé mais vérifiez mon édition – Deepak

Questions connexes