2010-11-24 22 views
38

J'essaie de mettre à jour la valeur d'une colonne dans un groupe de lignes dans une table en utilisant UPDATE. Le problème est que j'ai besoin d'utiliser une sous-requête pour dériver la valeur de cette colonne, et cela dépend de la même table. Voici la requête:SQL UPDATE avec sous-requête qui fait référence à la même table dans MySQL

UPDATE user_account student 
SET student.student_education_facility_id = (
    SELECT teacher.education_facility_id 
    FROM user_account teacher 
    WHERE teacher.user_account_id = student.teacher_id AND teacher.user_type = 'ROLE_TEACHER' 
) 
WHERE student.user_type = 'ROLE_STUDENT'; 

Habituellement, si l'enseignant et l'élève se trouvaient dans deux tables différentes, mysql ne s'en plaindrait pas. Mais comme ils sont tous les deux utilisent la même table, mysql vomit cette erreur à la place:

erreur 1093 (HY000): Vous ne pouvez pas spécifier la table cible « étudiant » pour la mise à jour dans la clause FROM

est-il de toute façon je peux forcer mysql à faire la mise à jour? Je suis 100% positif la clause from ne sera pas affectée car les lignes sont mises à jour.

Sinon, y a-t-il un autre moyen d'écrire cette mise à jour SQL pour obtenir le même effet?

Merci!

EDIT: Je pense que je l'ai eu à travailler:

UPDATE user_account student 
LEFT JOIN user_account teacher ON teacher.user_account_id = student.teacher_id 
SET student.student_education_facility_id = teacher.education_facility_id 
WHERE student.user_type = 'ROLE_STUDENT'; 

Répondre

42

Quelques références pour vous http://dev.mysql.com/doc/refman/5.0/en/update.html

UPDATE user_account student 
INNER JOIN user_account teacher ON 
    teacher.user_account_id = student.teacher_id 
    AND teacher.user_type = 'ROLE_TEACHER' 
SET student.student_education_facility_id = teacher.education_facility_id 
+5

Ce serait bien s'il y avait deux solutions: le spécifique et l'un un peu plus abstrait, avec plus clairs noms de table et de colonne, pour simplifier la lecture pour les personnes à la recherche pour une réponse générale, comme moi.En tout cas, la question et la réponse me satisfont, mais je le suggérais pour une meilleure compréhension de la communauté. Merci, et +1 aux deux – Nico

+2

Tout à fait d'accord avec @Nico à ce sujet. C'est pourquoi j'ai fourni un exemple abstrait avec des noms de colonnes et de tables plus clairs (http://stackoverflow.com/a/23772515/886539). J'ai également mis à jour la réponse de John Hartsock (m'a aidé beaucoup à créer mon exemple). –

-3
UPDATE user_account student, (
    SELECT teacher.education_facility_id as teacherid 
    FROM user_account teacher 
    WHERE teacher.user_account_id = student.teacher_id AND teacher.user_type = 'ROLE_TEACHER' 
) teach SET student.student_education_facility_id= teach.teacherid WHERE student.user_type = 'ROLE_STUDENT'; 
+0

Une petite explication est toujours meilleure et rend votre réponse plus précieuse. – ForceMagic

2
UPDATE user_account student 

SET (student.student_education_facility_id) = (

    SELECT teacher.education_facility_id 

    FROM user_account teacher 

    WHERE teacher.user_account_id = student.teacher_id AND teacher.user_type = 'ROLE_TEACHER' 

) 

WHERE student.user_type = 'ROLE_STUDENT'; 
5
UPDATE user_account 
SET (student_education_facility_id) = ( 
    SELECT teacher.education_facility_id 
    FROM user_account teacher 
    WHERE teacher.user_account_id = teacher_id 
    AND teacher.user_type = 'ROLE_TEACHER' 
) 
WHERE user_type = 'ROLE_STUDENT' 

ci-dessus sont la requête de mise à jour de l'échantillon ...

Vous pouvez écrire sous requête avec la mise à jour instruction SQL, vous n'avez pas besoin de donner le nom d'alias pour cette table. donne le nom d'alias à la table de sous-requête. J'ai essayé et ça fonctionne très bien pour moi ....

+0

Si aucun alias n'est spécifié dans la sous-requête, ne prend-il pas la colonne de la table interne? – Nishanthan

20

exemple abstrait avec plus clairs noms de table et de colonne:

UPDATE tableName t1 
INNER JOIN tableName t2 ON t2.ref_column = t1.ref_column 
SET t1.column_to_update = t2.column_desired_value 

Comme suggéré par @Nico

Hope this quelqu'un d'aide.

+3

bon travail, comme lui – Sinto

+1

Pour un exemple abstrait, la clause '' 'ON t2.ref_column = t1.column_to_update''' ne doit pas faire référence à' '' column_to_update'''. Le critère de jointure est probablement basé sur une colonne différente. – frankleonrose

2

J'avais besoin de ceci pour SQL Server. Ici, il est:

UPDATE user_account 
SET student_education_facility_id = cnt.education_facility_id 
from (
    SELECT user_account_id,education_facility_id 
    FROM user_account 
    WHERE user_type = 'ROLE_TEACHER' 
) as cnt 
WHERE user_account.user_type = 'ROLE_STUDENT' and cnt.user_account_id = user_account.teacher_id 

Je pense que cela fonctionne avec d'autres SGBDR (s'il vous plaît confirmer). J'aime la syntaxe parce qu'elle est extensible.

Le format que je avais besoin était ce fait:

UPDATE table1 
SET f1 = cnt.computed_column 
from (
    SELECT id,computed_column --can be any complex subquery 
    FROM table1 
) as cnt 
WHERE cnt.id = table1.id 
+0

ne fonctionne pas pour moi sur mysql – user1732055

+0

Fantastique J'ai utilisé quelque chose de similaire et a travaillé comme un charme, merci! (Serveur Microsoft SQL) –