如何以 R 列表的形式检索公共表表达式 (CTE)?

问题描述 投票:0回答:1

背景

我已连接到 PostgreSQL 数据库,并使用

dplyr
+
dbplyr
来查询它。其中一个查询相当长且复杂,并且使用多个 CTE。

问题

我需要使用这些 CTE 在 R 中进行一些绘图和分析,但我不知道如何将它们作为 R 中的“分离”数据帧。

我尝试将长查询分解为较小的查询,但当一个 CTE 需要前一个 CTE 时,这显然会失败。

问题

如何在 R 中以数据帧列表的形式检索查询的 CTE?

示例

请在下面找到一个说明问题的小例子。这个查询很愚蠢,但我觉得它足以用于说明目的。

# Packages ----
if(!require("dbplyr")){install.packages("dbplyr")}; library(dbplyr)
if(!require("tidyverse")){install.packages("tidyverse")}; library(tidyverse)

# Set up the example database using the iris dataset ----
con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
copy_to(con, iris)
# Query using the "WITH" command ----
query = sql(
  "WITH
  tbl_set AS (SELECT * FROM iris WHERE Species = 'setosa'),
  tbl_ver AS (SELECT * FROM iris WHERE Species = 'versicolor'),
  tbl_all AS (
    SELECT *
    FROM tbl_set 
    UNION ALL SELECT * FROM tbl_ver)
SELECT * FROM tbl_all"
)

预期产量

预期输出是 R 环境中的一个对象,例如包含每个 CTE 作为数据帧的列表,请参阅下面的预期结构:

# Target output ----
list(
  tbl_set = filter(iris, Species == "setosa"),
  tbl_ver = filter(iris, Species == "versicolor"),
  tbl_all = collect(tbl(con, query))
)
#> $tbl_set
#>    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1           5.1         3.5          1.4         0.2  setosa
#> 2           4.9         3.0          1.4         0.2  setosa
#> 3           4.7         3.2          1.3         0.2  setosa
#> 4           4.6         3.1          1.5         0.2  setosa
#> 
#> $tbl_ver
#>    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
#> 1           7.0         3.2          4.7         1.4 versicolor
#> 2           6.4         3.2          4.5         1.5 versicolor
#> 3           6.9         3.1          4.9         1.5 versicolor
#> 4           5.5         2.3          4.0         1.3 versicolor
#> 
#> $tbl_all
#> # A tibble: 100 × 5
#>    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#>           <dbl>       <dbl>        <dbl>       <dbl> <chr>  
#>  1          5.1         3.5          1.4         0.2 setosa 
#>  2          4.9         3            1.4         0.2 setosa 
#>  3          4.7         3.2          1.3         0.2 setosa 
#>  4          4.6         3.1          1.5         0.2 setosa 
#> # ℹ 90 more rows

创建于 2024-07-04,使用 reprex v2.1.0

sql r dplyr common-table-expression dbplyr
1个回答
0
投票

我真的不知道你的问题是什么;我想我会向您展示如何将 CTE 拆分到它们自己的表中?您的最终查询可以更改为使用或不使用它们,但重点是您将它们放在最终列表中。

该方法归结为复制并粘贴 CTE 的代码并添加一些样板,

CREATE TABLE name as 
以使查询具体化。

library(dbplyr)
library(tidyverse)
library(DBI)
# Set up the example database using the iris dataset ----
con <- dbConnect(RSQLite::SQLite(), ":memory:")
copy_to(con, iris)

original_query <-  sql("WITH
  tbl_set AS (SELECT * FROM iris WHERE Species = 'setosa'),
  tbl_ver AS (SELECT * FROM iris WHERE Species = 'versicolor'),
  tbl_all AS (
    SELECT *
    FROM tbl_set 
    UNION ALL SELECT * FROM tbl_ver)
SELECT * FROM tbl_all")

# make the CTE queries explicit ? 
q1 <- sql("CREATE TABLE tbl_set as SELECT * FROM iris WHERE Species = 'setosa'")
q2 <- sql("CREATE TABLE tbl_ver as SELECT * FROM iris WHERE Species = 'versicolor'")

dbExecute(conn = con, q1)
dbExecute(conn = con, q2)

list(
  tbl_set = tbl(con, "tbl_set") |> collect(),
  tbl_ver = tbl(con, "tbl_ver") |> collect(),
  tbl_all = tbl(con, original_query) |> collect()
)

© www.soinside.com 2019 - 2024. All rights reserved.