在R中连接(使用sqldf时相当于COALESCE)

时间:2016-07-05 14:48:06

标签: sql r sqldf

我试图创建一个审计报告,该报告采用呼叫记录数据[表1]并将其与时间表数据进行比较[表2]。我需要一个简单的查询来返回' OK'如果有与时间表数据匹配的呼叫日志数据[表1]的记录[表2]。

表1

Date            Project Code    Amount  Employee
11/2/15         30018           250     Tom Thompson
11/2/15         30018           500     John Johnson
11/2/15         20018           500     Jane Doe

表2

Project Code    Project Name    Employee       Hours    Dates
30012           A               Jane Doe       4        11/2/15
3200            B               Jane Doe       2        11/2/15
4               C               Jane Doe       1        11/2/15
20018           D               Jane Doe       1        11/2/15
4               C               John Johnson   6        11/2/15

我在R中使用sqldf包,运行以下内容:

test2 = sqldf("
    SELECT a.*,
    CASE
        WHEN
            a.Name = b.employee and a.Date=b.Dates AND
            a.Project like b.ProjectCode
        THEN 'Okay'
        ELSE 'Flag'
        END 'Audit'

    FROM Table_1 as a, Table_2 as b
    WHERE a.Name = b.employee
    GROUP BY a.Name
")

这不会返回我需要的东西。 Mantaining SQL logic我想连接表2(或分组)以产生:

Project Code            Employee    Dates
30012, 3200, 4, 20018   Jane Doe    11/2/15

我的想法是,我可以使用"喜欢"在上面的案例陈述中的陈述,它将起作用。

4 个答案:

答案 0 :(得分:2)

您可以使用aggregatepaste在基础R中实现所需的输出:

aggregate(Project_Code ~ Employee + Dates, data=df, paste, sep=",")
      Employee   Dates          Project_Code
1     Jane_Doe 11/2/15 30012, 3200, 4, 20018
2 John_Johnson 11/2/15                     4

还有一些其他函数会返回此结果。正如@nicola所提到的,您也可以使用toString来实现这一目标。另一个选项是c

aggregate(Project_Code ~ Employee + Dates, data=df, c)

看上面的结果。

但请注意,此数据的结构比首次出现时更复杂。以下是使用str输出c的结果:

  

'data.frame':2个obs。 3个变量:
   $ Employee:因子w / 2级“Jane_Doe”,“John_Johnson”:1 2
   $日期:因子w / 1级别“11/2/15”:1 1
   $ Project_Code:2的清单     .. $ 1.1:int 30012 3200 4 20018
    .. $ 1.2:int 4

所以程序代码变量本身就是一个列表。如果这是一个问题,您可以使用pastecollapse =", "参数使其返回单个字符串变量,该变量看起来或多或少相同:

aggregate(Project_Code ~ Employee + Dates, data=df, paste, collapse=", ")
      Employee   Dates          Project_Code
1     Jane_Doe 11/2/15 30012, 3200, 4, 20018
2 John_Johnson 11/2/15                     4

但结构更简单。

数据

df <- read.table(header=T, text="Project_Code  Project_Name    Employee    Hours    Dates
30012           A               Jane_Doe       4        11/2/15
3200            B               Jane_Doe       2        11/2/15
4               C               Jane_Doe       1        11/2/15
20018           D               Jane_Doe       1        11/2/15
4               C               John_Johnson   6        11/2/15")

答案 1 :(得分:1)

使用R,我们可以在两个数据集之间执行left_join,然后按“员工”,“日期”,paste“项目代码”(toString进行分组是paste(., collapse=', ')

的包装器
library(dplyr)
left_join(Table_2, Table_1, by = c("ProjectCode", "Dates" = "Date", "Employee")) %>% 
    group_by(Employee, Dates) %>%
    summarise(ProjectCode = toString(ProjectCode))
 #     Employee   Dates           ProjectCode
 #        <chr>   <chr>                 <chr>
 #1     Jane Doe 11/2/15 30012, 3200, 4, 20018
 #2 John Johnson 11/2/15                     4

正如@nicola所提到的,我们只能使用'Table_2'来获得输出

 Table_2 %>%
      group_by(Employee, Dates) %>%
      summarise(ProjectCode = toString(ProjectCode)) 
 #    Employee   Dates           ProjectCode
 #        <chr>   <chr>                 <chr>
 #1     Jane Doe 11/2/15 30012, 3200, 4, 20018
 #2 John Johnson 11/2/15                     4

数据

 Table_1 <- structure(list(Date = c("11/2/15", "11/2/15", "11/2/15"), 
 ProjectCode = c(30018L, 
 30018L, 20018L), Amount = c(250L, 500L, 500L), Employee = c("Tom Thompson", 
 "John Johnson", "Jane Doe")), .Names = c("Date", "ProjectCode", 
 "Amount", "Employee"), class = "data.frame", row.names = c(NA, -3L))

 Table_2 <- structure(list(ProjectCode = c(30012L, 3200L, 4L, 20018L, 4L), 
ProjectName = c("A", "B", "C", "D", "C"), Employee = c("Jane Doe", 
"Jane Doe", "Jane Doe", "Jane Doe", "John Johnson"), Hours = c(4L, 
2L, 1L, 1L, 6L), Dates = c("11/2/15", "11/2/15", "11/2/15", 
"11/2/15", "11/2/15")), .Names = c("ProjectCode", "ProjectName", 
"Employee", "Hours", "Dates"), class = "data.frame",
 row.names = c(NA, -5L))

答案 2 :(得分:1)

问题中的描述,输入,输出和代码都是不一致的(例如,代码指的是Name输入和Audit输出列但是没有出现在显示的输入和输出中)所以我们假设了Note中的输入结束,问题输出中显示的列并修改代码以解决不一致问题并使用group_concat

代码可能存在其他问题,但需要更多澄清解决这些问题的意图,特别是关于是否应该计算审计列,即使未在示例输出中进行计算,如果是,则确切地说它所代表的内容以及在该主题中对合并的引用是指什么。

library(sqldf)

sqldf("SELECT group_concat(b.ProjectCode) as 'Project Code', a.Name, b.Dates
              FROM Table_1 as a
              JOIN Table_2 as b ON a.Name = b.employee
              GROUP BY a.Name")

,并提供:

                 Project Code         Name   Dates
1          4,3200,20018,30012     Jane_Doe 11/2/15
2                           4 John_Johnson 11/2/15

注意:假设这些输入:

Lines1 <- "Date            Project    Amount  Name
11/2/15         30018           250     Tom_Thompson
11/2/15         30018           500     John_Johnson
11/2/15         20018           500     Jane_Doe"

Lines2 <- "ProjectCode    Name    Employee       Hours    Dates
30012           A               Jane_Doe       4        11/2/15
3200            B               Jane_Doe       2        11/2/15
4               C               Jane_Doe       1        11/2/15
20018           D               Jane_Doe       1        11/2/15
4               C               John_Johnson   6        11/2/15"

Table_1 <- read.table(text = Lines1, header = TRUE)
Table_2 <- read.table(text = Lines2, header = TRUE)

答案 3 :(得分:0)

您可以使用EXISTS子查询轻松完成此操作:

SELECT a.*,
       (CASE WHEN EXISTS (SELECT 1 FROM table_2 b WHERE a.Name = b.employee)
             THEN 'Okay'
             ELSE 'Flag'
        END) as Audit
FROM Table_1 a;