【问题标题】:Create glue string with mixture of single and double quotes使用单引号和双引号混合创建粘合字符串
【发布时间】:2020-08-22 05:48:38
【问题描述】:

我正在尝试使用R 中的glue 包创建一个字符串 这是 'single'"double" 引号的混合。

作为一个代表,考虑以下类型的SQL 查询 我要构建的字符串:

CREATE TABLE fact_final_table AS 
(SELECT tab1.id,
    AVG(tab2."MV") FILTER (WHERE tab2.record_dt BETWEEN tab1.start_date::date - integer '7'
                                                      AND tab1.start_date::date - integer '1') AS "mv_avg_1w",
    AVG(tab2."MV") FILTER (WHERE tab2.record_dt BETWEEN tab1.start_date::date - integer '14'
                                                      AND tab1.start_date::date - integer '1') AS "mv_avg_2w"
FROM (SELECT id,
             start_date,
             point
      FROM base_tab
      WHERE mpfb.start_date::date >= '01-01-2000'::date) AS tab1
LEFT JOIN ghcnd_observations AS tab2
    ON (tab2.record_dt BETWEEN (tab1.start_date::date - integer '180')
                           AND (tab1.start_date::date - integer '1')
        AND ST_DWithin(tab1.point, tab2.location, 0.5))
GROUP BY tab1.id);

如你所见,它是单引号和双引号的组合, 这对于按照上面所写的字面意思进行保存很重要。为了 例如tab2."MV" 有双引号,tab1.start_date::date - integer '7' AND tab1.start_date::date - integer '1' 有单引号 需要按字面意思保留的引号。

这个字符串也需要使用参数来构建。 我在R 中使用glue 尝试了以下操作,但无法得到它 上班。

var1       <- "MV"
var1_lowcase <- "mv"
lag_days   <- 180
var_date   <- as.Date("2000-01-01")
var_dwithin <- 0.5

glue::glue(
"CREATE TABLE fact_final_table AS 
(SELECT tab1.id,
    AVG(tab2."{var1}") FILTER (WHERE tab2.record_dt BETWEEN tab1.start_date::date - integer '7'
                           AND tab1.start_date::date - integer '1') AS "{var1_lowcase}_avg_1w",
    AVG(tab2."{var1}") FILTER (WHERE tab2.record_dt BETWEEN tab1.start_date::date - integer '14'
                           AND tab1.start_date::date - integer '1') AS "{var1_lowcase}_avg_2w"
    FROM (SELECT id,
          start_date,
          point
          FROM base_tab
          WHERE mpfb.start_date::date >= '{format(var_date, "%d-%m-%Y")}'::date) AS tab1
    LEFT JOIN ghcnd_observations AS tab2
    ON (tab2.record_dt BETWEEN (tab1.start_date::date - integer '{lag_days}')
        AND (tab1.start_date::date - integer '1')
        AND ST_DWithin(tab1.point, tab2.location, {var_dwithin}))
    GROUP BY tab1.id);")

不幸的是,由于没有单引号/双引号,这不起作用 在glue::glue(...) 中正确转义。

任何人都可以在这里提供最少的帮助吗 中断所需的输出字符串?我不确定这是否容易 可行的。我将不胜感激任何其他tidy 方法,例如例如,也使用stringr,因为我希望这对%&gt;% 友好。 我已经简要地查看了glue::glue_sql,但不知道如何直接 在这里应用它。如果适用,我将不胜感激在此处了解如何使用它。

【问题讨论】:

    标签: r tidyverse r-glue


    【解决方案1】:

    尝试转义双引号:

    glue::glue(
       "CREATE TABLE fact_final_table AS 
       (SELECT tab1.id,
       AVG(tab2.\"{var1}\") FILTER (WHERE tab2.record_dt BETWEEN tab1.start_date::date - integer '7'
       AND tab1.start_date::date - integer '1') AS \"{var1_lowcase}_avg_1w\",
       AVG(tab2.\"{var1}\") FILTER (WHERE tab2.record_dt BETWEEN tab1.start_date::date - integer '14'
       AND tab1.start_date::date - integer '1') AS \"{var1_lowcase}_avg_2w\"
       FROM (SELECT id,
             start_date,
              point
       FROM base_tab
        WHERE mpfb.start_date::date >= '{format(var_date, \"%d-%m-%Y\")}'::date) 
      AS tab1
       LEFT JOIN ghcnd_observations AS tab2
       ON (tab2.record_dt BETWEEN (tab1.start_date::date - integer '{lag_days}')
       AND (tab1.start_date::date - integer '1')
       AND ST_DWithin(tab1.point, tab2.location, {var_dwithin}))
       GROUP BY tab1.id);")
    

    返回:

    #CREATE TABLE fact_final_table AS 
    #(SELECT tab1.id,
    #AVG(tab2."MV") FILTER (WHERE tab2.record_dt BETWEEN tab1.start_date::date #- integer '7'
    #AND tab1.start_date::date - integer '1') AS "mv_avg_1w",
    #AVG(tab2."MV") FILTER (WHERE tab2.record_dt BETWEEN tab1.start_date::date #- integer '14'
    #AND tab1.start_date::date - integer '1') AS "mv_avg_2w"
    #FROM (SELECT id,
    #start_date,
    #point
    #FROM base_tab
    #WHERE mpfb.start_date::date >= '01-01-2000'::date) AS tab1
    #LEFT JOIN ghcnd_observations AS tab2
    #ON (tab2.record_dt BETWEEN (tab1.start_date::date - integer '180')
    #AND (tab1.start_date::date - integer '1')
    #AND ST_DWithin(tab1.point, tab2.location, 0.5))
    #GROUP BY tab1.id);
    

    【讨论】:

    • 我很欣赏这个答案。我昨天研究了类似的方法,发现使用glue::single_quote()glue::double_quote 函数有更明确的方法。请参阅下面的答案,我可能会选择
    【解决方案2】:

    所以我从昨天开始更详细地研究了这个问题,并且 看来glue 确实具有make single and double quotes explicit 的功能,即glue::single_quote()glue::double_quote().

    类似于@ronakshah 的(有用的)回应,我设法 以下,更明确(为了代码可读性):

    var1       <- "MV"
    var1_lowcase <- "mv"
    lag_days   <- 180
    var_date   <- as.Date("2000-01-01")
    var_dwithin <- 0.5
    
    glue::glue(
        "CREATE TABLE fact_final_table AS 
       (SELECT tab1.id,
       AVG(tab2.{glue::double_quote(var1)}) FILTER (WHERE tab2.record_dt BETWEEN tab1.start_date::date - integer '7'
       AND tab1.start_date::date - integer '1') AS {glue::double_quote(glue::glue({var1_lowcase},'_avg_1w'))},
       AVG(tab2.{glue::double_quote(var1)}) FILTER (WHERE tab2.record_dt BETWEEN tab1.start_date::date - integer '14'
       AND tab1.start_date::date - integer '1') AS {glue::double_quote(glue::glue({var1_lowcase},'_avg_2w'))}
       FROM (SELECT id,
             start_date,
              point
       FROM base_tab
        WHERE mpfb.start_date::date >= {glue::single_quote(format(var_date, '%d-%m-%Y'))}::date) 
      AS tab1
       LEFT JOIN ghcnd_observations AS tab2
       ON (tab2.record_dt BETWEEN (tab1.start_date::date - integer '{lag_days}')
       AND (tab1.start_date::date - integer '1')
       AND ST_DWithin(tab1.point, tab2.location, {var_dwithin}))
       GROUP BY tab1.id);")
    

    返回我需要的主字符串。希望这对其他人有帮助 谁有类似的glue 要求。

    【讨论】:

      猜你喜欢
      • 2014-02-17
      • 2010-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多