2011-03-17 2 views
0

Dans la table1, il y a une colonne nommée calendar_date, l'enregistrement est au format 10/8/2010, dans la table2 il y a une colonne nommée date, au format de 10/8. Dans la table2, il existe deux autres colonnes nommées daynoleap, dayleap, qui indique le numéro de date julien de l'année noleap ou de l'année bissextile. Maintenant, j'ai besoin d'ajouter une colonne de ces deux à table1, déterminée par l'année de la colonne calendar_date. Si c'est 2010, il est divisé par 4 et a un reste, donc j'ajoute la colonne daynoleap de table2 à la colonne julian_date de table1. Sinon, j'ajoute une colonne dayleap.Plus d'une ligne retournée par une sous-requête dans PostgreSQL

Je reçois une erreur: plus d'une ligne retournée par une sous-requête utilisée comme une expression, en utilisant les codes ci-dessous: (Je crois que l'erreur provient de l'instruction de requête pour le moment). Tous les codes sont dans un forloop, dans lequel j'ai eu un seul enregistrement de la variable de l'année (par exemple, 2010), monthDate (par exemple 10/8).

 while int(year)%4 == 0: 
      statement2="UPDATE table1 SET julian_date = (SELECT dayleap FROM table2 WHERE date = '%s') WHERE (SELECT date FROM table2) = '%s'" 
      statement2=statement2 % (monthDate, monthDate) 
      curs2 = conn.cursor() 
      curs2.execute(statement2,) 
      conn.commit() 

De toute évidence, il y a un problème avec les codes pour l'empêcher de mettre à jour un enregistrement unique. Mais puisque j'ai déjà une clause WHERE pour l'instruction de mise à jour, et je ne vois pas de problème avec l'instruction non plus. J'ai essayé de changer les deux valeurs à gauche et à droite du signe égal, etc., mais cela n'a pas fonctionné. Quelqu'un peut m'aider?

Solution:
Je résolu ce problème en utilisant les codes ci-dessous:

statement1='SELECT date FROM table1' 
    curs1.execute(statement1) 
    records1=curs1.fetchall() 
    for record1 in records1: 
     date = record1[0].split('/') 
     monthDate=date[0]+ '/'+date[1] 

     if int(year)%4 == 0: #for leap year 
      statement_tmp = "SELECT dayleap FROM table2 WHERE date = '%s'" % (monthDate) #the date column in table2 is in format of month/date. 
      curs1.execute(statement_tmp) 
      julianDate1 = curs1.fetchall() 
      julianDate = curs1.fetchall()[0][0] 
      statement = "UPDATE table1 SET juliandate = '%s' WHERE date = '%s'" % (julianDate, fullDate) 
      curs1.execute(statement) 
      conn.commit() 

     else: # for nonleap year 
+0

Etes-vous sûr qu'il n'y a pas deux enregistrements avec la même date dans votre base de données? Pour faire au moins erreur, vous pouvez ajouter une LIMIT 1 à la sous-requête ... – dcn

Répondre

0

J'ai résolu en séparant les instructions SELECT et UPDATE en celles séparées. En outre, dans l'instruction: SELECT column1 FROM table WHERE column2 = variable .. la colonne2 est supposée être dans la table, plutôt que d'une autre table. Sinon, il ne peut pas trouver les bons enregistrements à sélectionner ou à mettre à jour. Les conseils sont la clé pour résoudre le problème. Voir la solution dans la question. Merci

1

Vous essayez de définir julian_date à quelque chose que le retour sous la requête (qui retourne plus d'un résultat), mais vous pouvez N'attribuez pas plusieurs résultats. La sous-requête ne doit renvoyer qu'un seul résultat afin que vous puissiez définir julian_date.

Changer votre sous-requête à:

SELECT dayleap FROM table2 WHERE date = '%s' LIMIT 1 

et vous pouvez ajouter LIMIT 1 à votre 2ème sous requête ainsi.

+0

@ mike: oui, ça marche maintenant! im en utilisant print statement2 et il imprime des millions d'enregistrements, ce qui signifie que cela fonctionne maintenant.mais pour une raison quelconque, il ne met pas à jour les enregistrements à la table1. et qu'est-ce que cela pourrait être?谢谢 – widget

+0

Les chances sont que les clauses WHERE ne trouvent aucun résultat à mettre à jour. –

+0

Je me demande si l'instruction: UPDATE table SET colonne = (SELECT colonne2 FROM table2 ..) .. a un sens ou non. comment est-il censé être écrit? – widget

2

Ceci est une instruction de mise à jour très basique. Il devrait y avoir zéro sous-requêtes et les requêtes corrélées:

UPDATE table1 
    SET julian_date = dayleap 
FROM table2 
WHERE date = %s 

PS:

  • Je ne nommerai pas vos colonnes après les types de données (date). Bien que cela permette de vous mordre de manière subtile et insidieuse.
  • Votre espérons-s'échapper des données si provient d'une source non fiable et pas seulement le laisser tomber dans.
  • Cela semble être beaucoup de travail pour quelque chose de simple comme trouver une année bissextile. PostgreSQL sait déjà: select extract(day from (2003 || '-03-01')::date - '1 day'::interval) = 29 où vous pouvez paramétrer 2003 en n'importe quelle année
Questions connexes