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 :

UPDATE sur plusieurs colonnes à la fois


Sujet :

Requêtes MySQL

  1. #1
    Membre du Club Avatar de yuukuari
    Homme Profil pro
    Inscrit en
    Mai 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 65
    Points : 40
    Points
    40
    Par défaut UPDATE sur plusieurs colonnes à la fois
    Bonjour

    Je travaille sur une base de données assez conséquente et lorsque je fais un update classique, ça plante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE table SET champ1 = (requête1), champ2 = (requête2), etc..
    Donc j'ai décomposé la requête en faisant un update sur chaque colonne une par une:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    UPDATE table SET champ1 = (requête1);
    UPDATE table SET champ2 = (requête2);
    etc...
    Ca ne plante plus mais c'est un peu lourd à écrire tout ça :/ Surtout pour certains champs qui utilisent la même requête pour être remplis (comme si requête 1 = requête 2).

    Ma question est donc la suivante, peut-on faire un update de plusieurs champs d'une table de cette façon:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE table SET (champ1, champ2, champ3) = (requête);
    Par exemple (fictif :p) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    UPDATE `fruits` SET (`fruits`.`couleur`, `fruits`.`prix`) = (
         SELECT `aliments`.`couleur`, `aliments`.`prix` FROM `aliments`
         WHERE `aliments`.`type` = 'fruit'
    );
    Je ne sais pas si la commande existe, j'ai pas mal cherché et j'ai vu une seule personne en parler mais chez moi ça marche pas :/ Ce serait pratique quand même ^^

  2. #2
    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 : 61
    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 048
    Points
    34 048
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par yuukuari Voir le message
    Je travaille sur une base de données assez conséquente et lorsque je fais un update classique, ça plante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE table SET champ1 = (requête1), champ2 = (requête2), etc..
    Et tu récoltes quoi ? Un message d'erreur ?

    On peut voir la vraie requête avec une idée du volume et un exemple de données ?

  3. #3
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 034
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 034
    Points : 23 779
    Points
    23 779
    Par défaut
    Bonjour,

    Inspire-toi de la solution présentée dans la discussion suivante : http://www.developpez.net/forums/d82...date-jointure/

    ced

  4. #4
    Membre du Club Avatar de yuukuari
    Homme Profil pro
    Inscrit en
    Mai 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 65
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par CinePhil Voir le message
    Et tu récoltes quoi ? Un message d'erreur ?

    On peut voir la vraie requête avec une idée du volume et un exemple de données ?
    Le but c'est de calculer des statistiques à la semaine sur des bandes dessinées en ligne. Ça me permet de donner une note à chaque album et donc de les classer par "popularité à la semaine".

    La requête est la 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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    insert into `album_statistics` (album_id, created_on) 
    select `albums`.`id`, CURDATE() from `albums` where `albums`.`displayed` = 1 and `albums`.`deleted` = 0;
     
    update `album_statistics` set 
     
    	`album_statistics`.`week_fan_count` = (
    		select count(*) from `favorite_albums`
    		where (DATEDIFF(CURDATE(), `favorite_albums`.`created_on`) < 7) and `favorite_albums`.`album_id` = `album_statistics`.`album_id` and `album_statistics`.`created_on` = CURDATE()
    	),
     
    	`album_statistics`.`week_read_count` = (
    		select count(*) from `album_views`
    		where (DATEDIFF(CURDATE(), `album_views`.`date`) < 7) and `album_views`.`album_id` = `album_statistics`.`album_id` 
    		and `album_views`.`read` = 1 and `album_statistics`.`created_on` = CURDATE()
    	),
     
    	`album_statistics`.`week_critic_count` = (
    		select count(*) from `critics`
    		where (DATEDIFF(CURDATE(), `critics`.`created_on`) < 7) and `critics`.`album_id` = `album_statistics`.`album_id` and `album_statistics`.`created_on` = CURDATE()
    	),
     
    	`album_statistics`.`week_global_avg` = (
    		select avg(`critics`.`global_rating`) from `critics`
    		where (DATEDIFF(CURDATE(), `critics`.`created_on`) < 7) and `critics`.`album_id` = `album_statistics`.`album_id` and `album_statistics`.`created_on` = CURDATE()
    	),
     
    	`album_statistics`.`week_scenario_avg` = (
    		select avg(`critics`.`scenario_rating`) from `critics`
    		where (DATEDIFF(CURDATE(), `critics`.`created_on`) < 7) and `critics`.`album_id` = `album_statistics`.`album_id` and `album_statistics`.`created_on` = CURDATE()
    	),
     
    	`album_statistics`.`week_illustration_avg` = (
    		select avg(`critics`.`illustration_rating`) from `critics`
    		where (DATEDIFF(CURDATE(), `critics`.`created_on`) < 7) and `critics`.`album_id` = `album_statistics`.`album_id` and `album_statistics`.`created_on` = CURDATE()
    	)
    ;
     
    update `albums`, `album_statistics` 
    	set `albums`.`week_popularity` = (
    		calcul de popularité des albums
    	) 
    	where `albums`.`id` = `album_statistics`.`album_id` and `album_statistics`.`created_on` = CURDATE()
    ;
    Pour le volume de données, pour l'instant j'ai environ 360 albums, 1000 critiques et 120 000 lectures donc ça fait pas mal de données et quand je lance la requête complète la page mysql se bloque :/

    C'est pour ça que je l'ai séparée en plusieurs requêtes:

    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    update `album_statistics` 
    set `album_statistics`.`week_fan_count` = (
    	select count(*) from `favorite_albums`
    	where (DATEDIFF(CURDATE(), `favorite_albums`.`created_on`) < 7) and `favorite_albums`.`album_id` = `album_statistics`.`album_id` and `album_statistics`.`created_on` = CURDATE()
    );
     
    update `album_statistics` 
    set `album_statistics`.`week_critic_count` = (
    	select count(*) from `critics`
    	where (DATEDIFF(CURDATE(), `critics`.`created_on`) < 7) and `critics`.`album_id` = `album_statistics`.`album_id` and `album_statistics`.`created_on` = CURDATE()
    );
     
    update `album_statistics` 
    set `album_statistics`.`week_read_count` = (
    	select count(*) from `album_views`
    	where (DATEDIFF(CURDATE(), `album_views`.`date`) < 7) and `album_views`.`album_id` = `album_statistics`.`album_id` 
    	and `album_views`.`read` = 1 and `album_statistics`.`created_on` = CURDATE()
    );
     
    update `album_statistics` 
    set `album_statistics`.`week_global_avg` = (
    	select avg(`critics`.`global_rating`) from `critics`
    	where (DATEDIFF(CURDATE(), `critics`.`created_on`) < 7) and `critics`.`album_id` = `album_statistics`.`album_id` and `album_statistics`.`created_on` = CURDATE()
    );
     
    update `album_statistics` 
    set `album_statistics`.`week_scenario_avg` = (
    	select avg(`critics`.`scenario_rating`) from `critics`
    	where (DATEDIFF(CURDATE(), `critics`.`created_on`) < 7) and `critics`.`album_id` = `album_statistics`.`album_id` and `album_statistics`.`created_on` = CURDATE()
    );
     
    update `album_statistics` 
    set `album_statistics`.`week_illustration_avg` = (
    	select avg(`critics`.`illustration_rating`) from `critics`
    	where (DATEDIFF(CURDATE(), `critics`.`created_on`) < 7) and `critics`.`album_id` = `album_statistics`.`album_id` and `album_statistics`.`created_on` = CURDATE()
    );
    Pour les 4 champs utilisant les critiques (week_critic_count, week_global_avg, week_scenario_avg et week_illustration_avg) je pensais faire une seule requête pour simplifier les choses.

    Citation Envoyé par ced
    Bonjour,

    Inspire-toi de la solution présentée dans la discussion suivante : http://www.developpez.net/forums/d82...date-jointure/

    ced
    J'avais pas pensé à faire comme ça je vais essayer de voir si ça marche

  5. #5
    Membre du Club Avatar de yuukuari
    Homme Profil pro
    Inscrit en
    Mai 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 65
    Points : 40
    Points
    40
    Par défaut
    J'ai essayé de refaire un peu à la façon du lien que tu m'as envoyé (qui revient en fait un peu à mon update à la fin):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    UPDATE `albums`, `album_statistics` 
    	SET `albums`.`week_popularity` = (
    		calcul de popularité des albums
    	) 
    	WHERE `albums`.`id` = `album_statistics`.`album_id` AND `album_statistics`.`created_on` = CURDATE()
    ;
    J'ai donc fait ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    update `album_statistics`, `critics` 
    set `album_statistics`.`week_critic_count` = count(*),
    	`album_statistics`.`week_global_avg` = avg(`critics`.`global_rating`),
    	`album_statistics`.`week_scenario_avg` = avg(`critics`.`scenario_rating`),
    	`album_statistics`.`week_illustration_avg` = avg(`critics`.`illustration_rating`)
    where `album_statistics`.`album_id` = `critics`.`album_id` and (DATEDIFF(CURDATE(), `critics`.`created_on`) < 7) and `album_statistics`.`created_on` = CURDATE();
    Il me dit "#1111 - Utilisation invalide de la clause GROUP "
    J'ai l'impression que le count(*) c'est pas vraiment comme ça qu'on fait ..

  6. #6
    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 : 61
    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 048
    Points
    34 048
    Billets dans le blog
    14
    Par défaut
    Moi je ferais une table temporaire avec tous les comptages et ensuite je mettrais à jour avec une jointure sur la table temporaire.
    Ca ne ferait que deux requêtes et la table temporaire peut être indexée.

  7. #7
    Membre du Club Avatar de yuukuari
    Homme Profil pro
    Inscrit en
    Mai 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 65
    Points : 40
    Points
    40
    Par défaut
    Je connaissais pas les tables temporaires (je débute) mais ça a l'air vraiment bien :O

    Et surtout ça colle apparemment avec ce que j'ai envie de faire car à chaque fois que je passe mon script, je crée d'abord une ligne pour chaque album de la table `albums` dans ma table `album_statistics` puis je fais des traitements dessus et à la fin je calcule la popularité de l'album, que je sauvegarde dans un champ de la table `albums`.

    Là je me fais chi** à recréer des lignes dans la table chaque jour et toutes mes requêtes se font en fonction de la date du jour..

    En plus, comme ça je peux faire la même chose pour la popularité d'un album au mois, à l'année, etc...

  8. #8
    Membre du Club Avatar de yuukuari
    Homme Profil pro
    Inscrit en
    Mai 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 65
    Points : 40
    Points
    40
    Par défaut
    Bon en attendant d'utiliser une table temporaire, j'ai réussi à résoudre mon autre problème héhé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    update `album_statistics` as a 
    left outer join (
    	select c.`album_id`, count(*) as total, avg(c.`global_rating`) as global_rating, avg(c.`scenario_rating`) as scenario_rating, avg(c.`illustration_rating`) as illustration_rating
    	from `critics` as c 
    	inner join 
    	where DATEDIFF(CURDATE(), c.`created_on`) < 7
    	group by c.`album_id`
    ) as ca on a.`album_id` = ca.`album_id` 
    set a.`week_critic_count` = ifnull(ca.total, 0),
    	a.`week_global_avg` = ifnull(ca.global_rating, 0),
    	a.`week_scenario_avg` = ifnull(ca.scenario_rating, 0),
    	a.`week_illustration_avg` = ifnull(ca.illustration_rating, 0);
    En fait le select il fallait le faire DANS le join de tables
    J'ai rajouté le "left outer join" et les ifnull pour les cas où un album n'a pas de critique.

  9. #9
    Membre du Club Avatar de yuukuari
    Homme Profil pro
    Inscrit en
    Mai 2007
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 65
    Points : 40
    Points
    40
    Par défaut
    Et voilà en faisant une table temporaire tout marche niquel

    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    CREATE TEMPORARY TABLE `album_statistics` (
      `id` int(11) NOT NULL auto_increment,
      `album_id` int(11) NOT NULL,
      `week_fan_count` int(11) NOT NULL DEFAULT '0',
      `week_critic_count` int(11) NOT NULL DEFAULT '0',
      `week_read_count` int(11) NOT NULL DEFAULT '0',
      `week_global_avg` decimal(10,5) DEFAULT null,
      `week_illustration_avg` decimal(10,5) DEFAULT null,
      `week_scenario_avg` decimal(10,5) DEFAULT null,
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
     
    insert into `album_statistics` (album_id) 
    select `albums`.`id` from `albums` where `albums`.`displayed` = 1 and `albums`.`deleted` = 0;
     
    update `album_statistics` 
    set `album_statistics`.`week_fan_count` = (
    	select count(*) from `favorite_albums`
    	where (DATEDIFF(CURDATE(), `favorite_albums`.`created_on`) < 7) and `favorite_albums`.`album_id` = `album_statistics`.`album_id`
    );
     
    update `album_statistics` 
    set `album_statistics`.`week_read_count` = (
    	select count(*) from `album_views`
    	where (DATEDIFF(CURDATE(), `album_views`.`date`) < 7) and `album_views`.`album_id` = `album_statistics`.`album_id` 
    	and `album_views`.`read` = 1
    );
     
    update `album_statistics` as a 
    left outer join (
    	select c.`album_id`, count(*) as total, avg(c.`global_rating`) as global_rating, avg(c.`scenario_rating`) as scenario_rating, avg(c.`illustration_rating`) as illustration_rating
    	from `critics` as c 
    	inner join `albums` on `albums`.`id` = c.`album_id` 
    	where DATEDIFF(CURDATE(), c.`created_on`) < 7 and `albums`.`deleted` = 0 and `albums`.`displayed` = 1 
    	group by c.`album_id`
    ) as ca on a.`album_id` = ca.`album_id` 
    set a.`week_critic_count` = ifnull(ca.total, 0),
    	a.`week_global_avg` = ifnull(ca.global_rating, 0),
    	a.`week_scenario_avg` = ifnull(ca.scenario_rating, 0),
    	a.`week_illustration_avg` = ifnull(ca.illustration_rating, 0);
     
    update `albums` 
    inner join `album_statistics` on `albums`.`id` = `album_statistics`.`album_id` 
    	set `albums`.`week_popularity` = (
    		calcul de la popularité
    	) 
    	where `albums`.`id` = `album_statistics`.`album_id`
    ;
    Si j'ai le courage je ferai un script automatique ^^
    Merci de votre aide à tous les 2!

    yuukuari

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. update plusieurs colonnes à la fois
    Par nostress dans le forum SAS Base
    Réponses: 2
    Dernier message: 23/04/2009, 18h44
  2. Jointure avec conditions sur plusieurs colonnes
    Par ben53 dans le forum Langage SQL
    Réponses: 9
    Dernier message: 28/11/2005, 09h27
  3. Lister sur plusieurs colonnes dans état
    Par armagued dans le forum Access
    Réponses: 3
    Dernier message: 30/10/2005, 21h21
  4. Query sur plusieurs colonnes avec count(distinct...)
    Par Jeankiki dans le forum Langage SQL
    Réponses: 2
    Dernier message: 18/08/2004, 15h22
  5. update sur plusieurs nouvelles valeurs
    Par Mut dans le forum Langage SQL
    Réponses: 4
    Dernier message: 02/11/2003, 16h15

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