【问题标题】:Empty where clauses in mysql (while I am using RMySql dbGetQuery)mysql 中的空 where 子句(当我使用 RMySql dbGetQuery 时)
【发布时间】:2014-05-14 06:34:28
【问题描述】:

我想做一些与这些非常相似的事情:

When mysql WHERE clause is empty, return all rows

Possible to have PHP MYSQL query ignore empty variable in WHERE clause?

如果我作为子集的变量是NULL,我希望忽略 where 子句。但是,我正在使用 dbGetQuery 从 R 访问我的 MySQL 数据库。到目前为止,我有这样的代码

write_pid_clause = function(p_id=NULL){
 if(is.null(p_id)){return(NULL)}
 else {return(paste0("where project_id = ",p_id)  )}
}

如果未指定p_id,则写入正确的where 语句行为以及代码:

  dbGetQuery( con,paste0("select MIN(completion_date) from run ",write_pid_clause(p_id))))

这可以正常工作,但是,如果我希望在 where 子句中插入更多条件,例如如果我想在p_id = NULL 时添加条件and status = 'complete'

有人对我如何在 R 中优雅地做到这一点有什么好的想法吗?

编辑 这是更多代码来演示我正在尝试做的事情,这是关于加入后的and 子句(执行where 有点棘手)

make_and_clauses = function(p_id = "",start_date="", end_date=""){

 conditions = list(
   list(" and r.project_id ='", p_id,"'"),
   list(" and r.completion_date >= '",start_date,"'"),
   list(" and r.completion_date <= '", end_date, "'"))
 condition_values = c(p_id,start_date, end_date)
 conditions[which(condition_values =="")] <- ""
 conditions = unlist(conditions,recursive=TRUE)
 paste0(conditions,collapse="")

}

给出输出

> make_and_clauses(2,3,4)
[1] " and r.project_id ='2' and r.completion_date >= '3' and r.completion_date <= '4'"
> make_and_clauses(2,,4)
[1] " and r.project_id ='2' and r.completion_date <= '4'"
> make_and_clauses(,3,2)
[1] " and r.completion_date >= '3' and r.completion_date <= '2'"

>

【问题讨论】:

  • 我认为没有一种简单/简单/清晰的方法可以实现您想要的。如果您希望能够添加多个子句,每个子句都依赖于变量的内容,则必须构建每个子句。我能想到的唯一相关的 SQL 技巧是将 WHERE 1=1 放入 SQL 语句中,然后为每个值添加 AND column = value。这样,如果你漏掉一个,语法仍然是正确的。
  • 嗨,听起来确实不错。请参阅我为处理多个缺失案例而编写的新代码。在那种情况下,Where 1 = 1 命令正是我处理必须使用where 的情况所需要的。如果您将其发布为答案,我会投票赞成:)

标签: mysql sql r rmysql


【解决方案1】:

从你的功能开始,我提出了类似的建议:

make_and_clauses <- function(p_id, start_date, end_date) {
    conditions = c(
        if (!missing(p_id)) sprintf("r.project_id ='%i'", p_id),
        if (!missing(start_date)) sprintf("r.completion_date >= '%i'", start_date),
        if (!missing(end_date)) sprintf("r.completion_date <= '%i'", end_date)
    )
    paste(conditions, collapse=" and ")
}

返回:

make_and_clauses(2,3,4)
# [1] "r.project_id ='2' and r.completion_date >= '3' and r.completion_date <= '4'"
make_and_clauses(2,,4)
# [1] "r.project_id ='2' and r.completion_date <= '4'"
make_and_clauses(,3,2)
# [1] "r.completion_date >= '3' and r.completion_date <= '2'"
make_and_clauses(,3,)
# [1] "r.completion_date >= '3'"

根本没有争论会导致什么重要:

make_and_clauses(,,)
# [1] ""

所以可以写WHERE子句:

make_and_clauses <- function(p_id, start_date, end_date) {
    conditions = c(
        if (!missing(p_id)) sprintf("r.project_id ='%i'", p_id),
        if (!missing(start_date)) sprintf("r.completion_date >= '%i'", start_date),
        if (!missing(end_date)) sprintf("r.completion_date <= '%i'", end_date)
    )
    if (length(conditions)>0) paste("WHERE", paste(conditions, collapse=" and ")) else ""
}

并将其用作

paste("select MIN(completion_date) from run", make_and_clauses(,3,2))
# [1] "select MIN(completion_date) from run WHERE r.completion_date >= '3' and r.completion_date <= '2'"
paste("select MIN(completion_date) from run", make_and_clauses())
# [1] "select MIN(completion_date) from run "

【讨论】:

  • 谢谢。这正是我所需要的,无需求助于where 1 = 1。我特别喜欢!missingsprintf 的用法。现在将第一批代码转换为可以处理任意参数列表的代码。
  • 类似lapply( as.list(args(make_and_clauses), function(arg) {if(!missing(arg)) sprintf(arg, eval(arg)})...
【解决方案2】:

我认为没有一种简单/简单/清晰的方法可以实现您想要的。如果您希望能够添加多个子句,每个子句都依赖于变量的内容,则必须构建每个子句。我能想到的唯一相关的 SQL 技巧是将 WHERE 1=1 放入 SQL 语句中,然后为每个值添加 AND column = value。这样,如果你漏掉一个,语法仍然是正确的。

我看到@Marek 提供了带有代码的答案;也许您可以结合这些答案来产生一个可行的解决方案。

【讨论】:

  • status 也可以为空。此外,where 子句可能包含超过 2 个条件检查,编写所有可能的 if 子句变得不切实际。
猜你喜欢
  • 2013-12-03
  • 2011-05-11
  • 2010-10-08
  • 1970-01-01
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 2011-11-25
相关资源
最近更新 更多