IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

[Optimisation] SELECT valeur selon dates multiples


Sujet :

Requêtes MySQL

  1. #1
    Membre à l'essai
    Inscrit en
    Août 2004
    Messages
    24
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Août 2004
    Messages : 24
    Points : 21
    Points
    21
    Par défaut [Optimisation] SELECT valeur selon dates multiples
    Bonjour à tous,

    Je me permet de créer ce post en désespoir de cause...
    Voici mon problème :

    J'ai une table (sous MySQL: 5.0.51a) assez simple de ce type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Champ		Type
    ownerID 	bigint(20)	INDEX
    balance 	decimal(22,2)
    date		datetime	INDEX
    Mais qui contient quelques millions de lignes.
    Les dates ne sont pas fixes (environs toutes les 10 minutes avec des trous de plusieurs heures possible, ainsi qu'un décalage dans le temps, genre : 2011-10-18 06:09:58, 2011-10-18 06:20:19,...)

    Dans ces lignes, j'aurais besoin de récupérer pour un ownerID, la valeur de balance actuelle, la balance -1 semaine et la balance -1 mois.

    j'utilise pour le moment la requête suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    SELECT
    	( SELECT	`balance`
    	FROM		`table`
    	WHERE		`ownerID`='.$_POST['characterID'].'
    	AND		`date` > DATE_ADD(UTC_TIMESTAMP(),INTERVAL -2 HOUR)
    	ORDER BY	`date` DESC
    	LIMIT		0,1) `balance`,
    	( SELECT	`balance`
    	FROM		`table`
    	WHERE		`ownerID`='.$_POST['characterID'].'
    	AND		`date` BETWEEN DATE_ADD(DATE_ADD(UTC_TIMESTAMP(),INTERVAL -1 WEEK),INTERVAL -1 DAY) AND DATE_ADD(UTC_TIMESTAMP(),INTERVAL -2 HOUR)
    	ORDER BY	`date` DESC
    	LIMIT		0,1) `balance7`,
    	( SELECT	`balance`
    	FROM		`table`
    	WHERE		`ownerID`='.$_POST['characterID'].'
    	AND		`date` BETWEEN DATE_ADD(DATE_ADD(UTC_TIMESTAMP(),INTERVAL -1 MONTH),INTERVAL -1 DAY) AND DATE_ADD(UTC_TIMESTAMP(),INTERVAL -2 HOUR)
    	ORDER BY	`date` DESC
    	LIMIT		0,1) `balance30`;
    Ce n'est pas propre du tout, j'appelle 3 fois une table assez grosse, ce qui plombe complètement les perfs de la requête...

    J'aimerais donc savoir si on peut appeler une seule fois la table et récupérer les 3 valeurs souhaitées en une fois

    NB : que les valeurs soient sous la forme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT balance,balance7,balance30
    ou où date correspond aux 3 dates recherchées, avec un résultat sur 3 lignes m'importe peu.


    Voilà, j'espère avoir été assez clair, et surtout j'attends vos remarques avec impatience !

    Merci d'avance à tout ceux qui prendront du temps pour me répondre

  2. #2
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Saluton,
    A priori, il suffirait de relier les 3 conditions dans la clause WHERE avec des OR mais, chaque condition pouvant retourner plusieurs lignes (d'où la présence des LIMIT 0,1), je ne vois pas de remède.
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

  3. #3
    Membre à l'essai
    Inscrit en
    Août 2004
    Messages
    24
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Août 2004
    Messages : 24
    Points : 21
    Points
    21
    Par défaut
    En fait, j'utilise les "LIMIT" seulement pour récupérer la première ligne.
    S'il y a une solution pour récupérer la valeur juste avant ou juste après (ça n'a aucune importance) la date voulu, on peut se débarrasser des "LIMIT" et à fortiori "DATE BETWEEN".

  4. #4
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    bonjour,

    Je ne vois pas trop non plus comment on pourrai optimiser une telle demande.

    Vous demandez 3 besoins distinct dans une même requête, et vu que la réponse à ces besoin est "flou" y a pas 36 solutions.

    Un axe vers lequel je me pencherai serai :
    - création d'un index : ownerID, date desc (, balance)

    En passant appeler une colonne 'date' est une mauvaise idée c'est un mot clef du SGBD.

    Ensuite avec cet index essayez différente approche de la solution, la votre et aussi une à base d'union all.

    => Voir si il y a des gains.

  5. #5
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    j'aurais besoin de récupérer pour un ownerID, la valeur de balance actuelle, la balance -1 semaine et la balance -1 mois.
    Balance actuelle d'un ownerID :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT balance AS balance_actuelle
    FROM la_table
    WHERE ownerID = ".intval($_POST['characterID'])."
    	AND la_date =
    	(
    		SELECT MAX(la_date)
    		FROM la_table
    		WHERE ownerID = ".intval($_POST['characterID'])."
    	)
    Balance d'il y a une semaine, en supposant qu'il y a au moins une ligne par jour dans la table :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT balance AS balance_de_la_semaine_derniere
    FROM la_table
    WHERE ownerID = ".intval($_POST['characterID'])."
    	AND la_date =
    	(
    		SELECT MAX(la_date)
    		FROM la_table
    		WHERE ownerID = ".intval($_POST['characterID'])."
    			AND DAYOFYEAR(la_date) = DAYOFYEAR(DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY))
    	)
    Chercher le mois dernier est une opération normalement interdite par la norme SQL. SQLPro a écrit quelque chose là-dessus dans son blog mais je ne retrouve pas où. Cependant, je crois que MySQL le gère.

    Regarde si tu peux regrouper les deux requêtes de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    SELECT
    	CASE
    		WHEN la_date =
    		(
    			SELECT MAX(la_date)
    			FROM la_table
    			WHERE ownerID = ".intval($_POST['characterID'])."
    		) THEN balance
    	END AS balance_actuelle,
    	CASE
    		WHEN la_date =
    		(
    			SELECT MAX(la_date)
    			FROM la_table
    			WHERE ownerID = ".intval($_POST['characterID'])."
    				AND DAYOFYEAR(la_date) = DAYOFYEAR(DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY))
    		) THEN balance
    	END AS balance_de_la_semaine_derniere
    	-- mois dernier à développer de la même manière
    FROM la_table
    WHERE ownerID = ".intval($_POST['characterID'])."
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

Discussions similaires

  1. [XL-2007] Selection de valeur selon liste déroulante
    Par Shades dans le forum Excel
    Réponses: 6
    Dernier message: 13/10/2011, 10h16
  2. [Toutes versions] Selection range selon valeur
    Par Kirgerad dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 07/04/2010, 13h12
  3. problème report des valeurs selon date
    Par Bricoltou dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 06/12/2009, 13h52
  4. Suppression des valeurs selon la date
    Par nefertari dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 08/01/2008, 10h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo