带有内部联接的R SQL Update语句

时间:2016-10-05 20:23:54

标签: sql r join

以下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;

3 个答案:

答案 0 :(得分:1)

有几个问题:

  1. 问题中的一行代码将IncomeRider设置为&#39; N&#39;而另一个是“Y&#39;我们假设您的意思是&#39; Y&#39;

  2. sqlite不支持update中的连接(但它确实支持相关的子查询)。有关sqlite中update的语法,请参阅:https://www.sqlite.org/lang_update.html

  3. 问题中显示的代码是尝试更新NewData,但IncomeRider是Inforce中的一列,而不是NewData。

  4. update不返回结果 - 它只在sqlite中执行表的更新 - 因此sqldf参数中需要select来返回一些内容。

  5. 解决这些问题我们有:

    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"