Il faut bien comprendre que la table (construite sur la base d'un enregistrement au maximum par jour) fait plusieurs centaines de lignes.
Elle contient les colonnes id, datevente et valeurvente (=>ce sont les montants journaliers du chiffre d'affaires d'un commerce)
Je cherche à obtenir par requête un tableau constitué de la date de chaque enregistrement et du cumul des ventes sur une période (en réalité 1 an mais pour les besoins de l'exemple j'ai mis 2 jours).
Voici le dump du tableau que je souhaite obtenir:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
array:5 [▼
0 => array:2 [▼
"datevente" => "29-04-2019"
"cumul deux derniers jours" => 4200
]
1 => array:2 [▼
"datevente" => "28-04-2019"
"cumul deux derniers jours" => 5000
]
2 => array:2 [▼
"datevente" => "27-04-2019"
"cumul deux derniers jours" => 4000
]
3 => array:2 [▼
"datevente" => "25-04-2019"
"cumul deux derniers jours" => 5500
]
4 => array:2 [▼
"datevente" => "24-04-2019"
"cumul deux derniers jours" => 2000
]
]
Le cumul des ventes des deux derniers jours du 29 au 28 avril => 4200
Le cumul des ventes des deux derniers jours du 28 au 27 avril => 5000
Le cumul des ventes des deux derniers jours du 27 au 26 avril => 4000 <- le 26 est un dimanche, pas de vente et pas d'enregistrement dans la table
Le cumul des ventes des deux derniers jours du 25 au 24 avril => 5500
Le cumul des ventes des deux derniers jours du 24 au 23 avril => 2000 <- pour l'exemple la table s'arrête au 24 avril.
Quelle requête me permet d'obtenir cette table [datevente, somme glissante sur une période de x jours]? Cela paraît simple mais je sèche depuis plusieurs jours.
Dans le principe, à moins d'introduire des conditions, ta requête n'a pas de sens "absolu" : tu as bien une première date et donc la période ne veut pas dire quelque chose pour tous les enregistrements.
Tu as l'air de travailler en php, et ce que tu veux faire est très facile à faire en construisant le tableau au fur et à mesure de l'affichage. Pourquoi chercher à le faire directement dans la requête ?
C'est effectivement assez facile à faire en php .... mais cela nécessite deux boucles imbriquées, la première qui tourne sur tous les enregistrements, la deuxième qui vérifie pour chacun des enregistrements si on est dans la période, et si oui qui fait la somme.
Il y a environ 300 enregistrements par an (pas de vente le Dimanche et jours fériés.
Comme j'ai dix années d'historique, cela fait 3000 fois 3000 vérifications à faire soit 9 000 000.
Inutile de dire que j'ai l'impression qu'une requête native sur la base sera plus efficace. Non?
Voici le script php qui donne le résultat, il tourne en 1,8 seconde sur une profondeur de 2,5 années:
Ben, je ne vois pas trop en quoi ce serait plus efficace, il va falloir faire le même travail. On ne peut pas savoir dans une seule requête, à l"avance; ce qu'il y a dans chaque période. Le plus compliqué est plus de trouver un algo efficace.
Personnellement, je ferais une requête préparée en incrémentant la période et en faisant autant d'execute que de périodes.
Je ne suis pas sûr d'avoir saisi ... mais selon moi une seule requête peut faire le taff :
SELECT
T1.id,
T1.datevente,
T1.valeurvente,
SUM(T2.valeurvente) AS cumul_periode
FROM
matable T1
LEFT JOIN matable T2
ON T1.datevente >= T2.datevente
AND T2.datevente >= T1.datevente - INTERVAL 2 DAY
GROUP BY
T1.id,
T1.datevente,
T1.valeurvente
ORDER BY T1.datevente
Dans la jointure on change la période glissante avec celle voulue, ici j'ai mis 2 jours.
Tout d'abord merci pour la proposition de requête sql qui m'a bien aidé. J'ai été amené à la transformer car a priori le left join ne fonctionne pas sur une jointure d'une table avec elle-même.
Voici la requete qui fonctionne:
SELECT ca1.datevente as date,SUM(ca2.champ) as cumul
FROM CA ca1
JOIN CA ca2
WHERE ca2.datevente BETWEEN DATE_SUB(ca1.datevente,INTERVAL 2 DAY) AND ca1.datevente
GROUP BY ca1.datevente
Comme tu l'as proposé le DATE_SUB(ca1.datevente,INTERVAL 2 DAY) fonctionne aussi avec - INTERVAL 2 DAY à la place.
Le problème est que je veux ôter un intervalle composite de jours, mois et année. Ainsi, si je mets DATE_SUB(ca1.datevente,INTERVAL 1 YEAR 2 DAY) ou - INTERVAL 1 YEAR 2 DAY j'ai en retour l'erreur que voici:
SQLSTATE[42000]: Syntax error or access violation: 1064 Erreur de syntaxe près de '2 DAY) AND ca1.datevente GROUP BY ca1.datevente' à la ligne 1
Ne saurais-je pas bien écrire la syntaxe de cette fonction INTERVAL?
a priori le left join ne fonctionne pas sur une jointure d'une table avec elle-même
Il n'y a pas de raison ... il y avais une erreur ? Si tu n'utilises pas de jointure externe (ici LEFT JOIN) la requête ne retournera pas les dates pour lesquelles il n'y a pas de valeurs précédentes ... pour la première date de l'intervalle notamment ...
CarréDas1 a écrit:
je veux ôter un intervalle composite de jours, mois et année
La syntaxe INTERVAL n'accepte pas plusieurs arguments ... le plus simple c'est de "cumuler" les INTERVAL :
ca1.datevente - INTERVAL 1 YEAR - INTERVAL 2 MONTH - INTERVAL 5 DAY
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Site les mathématiques amusantes pour vous détendre
N'oubliez pas d'activer les erreurs PDO.
Site les mathématiques amusantes pour vous détendre
N'oubliez pas d'activer les erreurs PDO.
Site les mathématiques amusantes pour vous détendre
Site les mathématiques amusantes pour vous détendre
Site les mathématiques amusantes pour vous détendre