PostgreSQL中的子查询返回多行
在表格1中,有一列叫做calendar_date,记录的格式是10/8/2010;在表格2中,有一列叫做date,格式是10/8。表格2还有另外两列,分别叫做daynoleap和dayleap,这两列表示的是平年和闰年的儒略日号。现在我需要根据calendar_date这一列的年份,往表格1中添加这两列中的一列。如果年份是2010,除以4后有余数,那么我就把表格2中的daynoleap列加到表格1的julian_date列里。否则,我就把dayleap列加到里面。
我遇到了一个错误:子查询返回了多于一行,导致无法作为表达式使用,使用下面的代码时出现了这个问题:(我认为错误出在查询语句上)。所有的代码都在一个循环里,在这个循环中我得到了年份(例如2010)和月份日期(例如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()
显然,代码中有些地方出错了,导致无法获取单条记录进行更新。不过我已经在更新语句中加了WHERE条件,我觉得这个语句没有问题。我尝试过把等号两边的值交换等等,但都没有用。有没有人能帮我解决这个问题?
解决方案:
我用下面的代码解决了这个问题:
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
3 个回答
你正在尝试把一个叫做 julian_date 的变量设置为一个子查询返回的值,但这个子查询返回了多个结果,而你不能把多个结果直接赋值给一个变量。子查询应该只返回一个结果,这样你才能给 julian_date 赋值。
你可以把你的子查询改成这样:
SELECT dayleap FROM table2 WHERE date = '%s' LIMIT 1
另外,你可能还想在你的第二个子查询中加上 LIMIT 1,这样它只会返回一个结果。
这是一个非常基础的更新语句。里面应该没有子查询和相关查询:
UPDATE table1
SET julian_date = dayleap
FROM table2
WHERE date = %s
补充说明:
- 我建议不要用数据类型来命名你的列,比如“日期”。虽然这样做是可以的,但可能会在一些微妙的地方给你带来麻烦。
- 如果数据来自不可信的来源,记得要对数据进行处理,而不是直接放进去。
- 对于像判断闰年这样简单的事情,这似乎做了很多工作。其实PostgreSQL已经知道答案了:
select extract(day from (2003 || '-03-01')::date - '1 day'::interval) = 29
,你可以把2003替换成任何年份。
我通过把SELECT和UPDATE这两个语句分开来解决了问题。另外,在这个语句中:SELECT column1 FROM table WHERE column2 = variable,column2应该是在这个表里面,而不是来自其他表。否则,它就找不到正确的记录来选择或更新。这些提示是解决问题的关键。具体的解决方法可以在问题中看到。谢谢!