以下SQL语句在Microsoft Access中有效,但在使用SQLDF时不在R中。我相信这是因为SQLDF是SQLite,并且它不支持更新语句中的连接。问题是,我不知道如何解决这个问题。 如何在R中完成以下更新?
UPDATE NewData INNER JOIN Inforce ON NewData.ContractNumber = Inforce.PolicyNumber SET Inforce.IncomeRider = "N" WHERE (((NewData.[Rider Termination Date])<=[Inforce].[FileDate]));
我试过R:
sqldf('UPDATE NewData INNER JOIN Inforce ON NewData.ContractNumber = Inforce.PolicyNumber SET Inforce.IncomeRider = "Y" WHERE ((NewData.[Rider Termination Date])>[Inforce].[FileDate])')
并收到此错误:
sqliteSendQuery(con,statement,bind.data)中的错误: 声明中的错误:接近&#34; INNER&#34;:语法错误
这不必由SQL语句完成,但认为这对我来说最容易,因为我已经有了一个有效的SQL语句。
NewData <- data.frame(ContractNumber=c(1,2,3),
RiderTerminationDate=c(as.Date(c("2015-01-01","2015-06-01","2016-05-01"))))
Inforce <- data.frame(PolicyNumber=c(1,2,3,4),
IncomeRider=c('Y','N','N','N'),
FileDate=c(as.Date(c("2014-01-01","2013-01-01","2016-08-01","2016-02-01"))))
结果IncomeRider应该是&#39; Y&#39; N&#39; Y&#39; Y&#39; N&#39; N&#39;
答案 0 :(得分:1)
有几个问题:
问题中的一行代码将IncomeRider
设置为&#39; N&#39;而另一个是“Y&#39;我们假设您的意思是&#39; Y&#39;
sqlite不支持update
中的连接(但它确实支持相关的子查询)。有关sqlite中update
的语法,请参阅:https://www.sqlite.org/lang_update.html
问题中显示的代码是尝试更新NewData,但IncomeRider是Inforce中的一列,而不是NewData。
update不返回结果 - 它只在sqlite中执行表的更新 - 因此sqldf参数中需要select来返回一些内容。
解决这些问题我们有:
sqldf(c("update Inforce
set IncomeRider = 'Y'
where fileDate >= (select n.RiderTerminationDate
from NewData n
where n.ContractNumber = Inforce.PolicyNumber)",
"select * from Inforce"))
,并提供:
PolicyNumber IncomeRider FileDate
1 1 Y 2014-01-01
2 2 N 2013-01-01
3 3 Y 2016-08-01
4 4 N 2016-02-01
sqldf语句返回更新后的Inforce
,但您仍需将其分配给Infoce
或其他变量:Inforce_updated <- sqldf(...)
2)问题的海报也发布了答案,尽管它提供的结果与问题中的要求不同。在该答案中,不是对Inforce中的行子集执行更新,而是返回合并的数据框,其中完全忽略现有的IncomeRider列,并且除非满足所需的条件,否则将其设置为N.如果这是想要的,那么试试这个:
sqldf("select PolicyNumber,
case when RiderTerminationDate is null or
FileDate >= RiderTerminationDate
then
'N'
else
'Y'
end IncomeRider,
FileDate,
RiderTerminationDate
from Inforce
left join NewData on ContractNumber = PolicyNumber")
,并提供:
PolicyNumber IncomeRider FileDate RiderTerminationDate
1 1 Y 2014-01-01 2015-01-01
2 2 Y 2013-01-01 2015-06-01
3 3 N 2016-08-01 2016-05-01
4 4 N 2016-02-01 <NA>
答案 1 :(得分:0)
可能你应该使用这个sintax
UPDATE NewData
SET Inforce.IncomeRider = "Y"
FROM NewData
INNER JOIN Inforce ON NewData.ContractNumber = Inforce.PolicyNumber
WHERE ((NewData.[Rider Termination Date])>[Inforce].[FileDate])
或使用别名
UPDATE ti
SET Inforce.IncomeRider = "Y"
FROM NewData as t1
INNER JOIN Inforce ON t1.ContractNumber = Inforce.PolicyNumber
WHERE ((t1.[Rider Termination Date])>[Inforce].[FileDate])
答案 2 :(得分:0)
我还没有机会复习上述答案(但我会)。我找到了解决问题的不同方法。我将NewData中的列名从ContractNumber更改为PolicyNumber,然后将2个数据帧合并在一起并更新了IncomeRider字段。
MergedData = merge(Inforce,NewData,by = 'PolicyNumber',all.x = TRUE)
# Update Transactions.IBR with 'Y' where NewData.RiderTermination > Transactions.FileDate
MergedData$IncomeRider[MergedData$RiderTerminationDate > MergedData$FileDate] <- "Y"
# Update Transactions.IBR with 'N' where NewData.RiderTermination <= Transactions.FileDate
MergedData$IncomeRider[MergedData$RiderTerminationDate <= MergedData$FileDate] <- "N"
# Update IBR with 'N' where Newdata.RiderTermination is NA
MergedData$IncomeRider[is.na(MergedData$RiderTerminationDate)] <- "N"