我已连接到 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
我真的不知道你的问题是什么;我想我会向您展示如何将 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()
)