POSTGRESQL:使用连接表的案例
Posted
技术标签:
【中文标题】POSTGRESQL:使用连接表的案例【英文标题】:POSTGRESQL: Using case with joined tables 【发布时间】:2021-04-15 02:20:59 【问题描述】:我是 Postgresql 新手,所以在这里仍然有点挣扎。请温柔一点。
我要加入三个表,并希望能够使用 case 语句来引入另一列,该列基于另一列带来所需值。我猜我的 INNER JOIN 和 CASE 语句是从前到后的,但我不确定如何在不破坏意图的情况下重新排列它们。
基本上:如果model_best_fit == SUNNY,那么我想要一个名为applied_f_model_hours_above4k 的新列具有来自hourabove4k_sunny 列的值
代码示例:
SELECT *
FROM px_fuel_weathercell
INNER JOIN f_descriptions ON px_f_weathercell.px_id = f_descriptions.fuel_id
INNER JOIN dailywx ON px_f_weathercell.fid_new_wx_cells = dailywx.location
CASE best_model_fit
WHEN 'SUNNY' then hoursabove4k_sunny
END applied_f_model_hours_above4k
WHERE best_model_fit = 'SUNNY' /* limiting my test case here, clause will be removed later */
LIMIT 1000;
错误如下:
ERROR: syntax error at or near "CASE"
LINE 5: CASE best_model_fit
^
SQL state: 42601
Character: 210
感谢您提供的任何帮助。
奖励积分:CASE 似乎很慢。运行此查询需要 45 秒。 dailywx 有 400,000 行,px_f_weathercell 有 6,000,000 行。有没有更快的方法来做到这一点?
编辑: 进行了以下编辑,当所需的列中包含数字(包括 0)时,不会得到一个充满空值的列。两列都是 double 类型。
EDIT2:更新了几个表名以指示列的来源。还更新为显示左连接。我还使用 PGTune 设置了一些推荐设置,以解决进程受磁盘限制的情况。我还在 px_f_weathercell.fid_new_wx_cells 和 px_f_weathercell.px_id 上设置了索引。这导致在大约 5-7 秒内返回 100,000 条记录。 不过,我仍在从 CASE 语句中接收空值。
SELECT *,
CASE best_model_fit
WHEN 'SUNNY' then dailywx.hoursabove4k_sunny
END applied_f_model_hours_above4k
FROM px_fuel_weathercell
LEFT JOIN f_descriptions ON px_f_weathercell.px_id = f_descriptions.fuel_id
LEFT JOIN dailywx ON px_f_weathercell.fid_new_wx_cells = dailywx.location
WHERE fuel_descriptions.best_model_fit = 'SUNNY' /* limiting my test case here, clause will be removed later */
LIMIT 1000;
【问题讨论】:
将 case expression 移动到你的select
(这是确定列数的地方)
我已经尝试了我认为您的意思,但没有得到一个充满空值的列。至少,这是向前迈出的一步。在上面编辑。
你也是inner joining
三个表,没有左加入。如果您没有在查询中放置某种类型的过滤器,那么您将遇到大多数(所有)记录的笛卡尔积,这意味着您可能会进行全表扫描(慢,不是真的使用索引,因为没有理由)。您能否编辑您的问题以显示其中一些列的来源?例如,我们不知道best_model_fit
或hoursabove4k_sunny
来自哪里。
@ps2goat,感谢有关笛卡尔查询的指针。我已更改为预期的左连接,设置了上面提到的索引广告,并处理了内存和缓存大小以响应注意到该进程是磁盘 io 绑定的。我仍在苦苦挣扎的是为什么 CASE 语句返回 null。
通常您指定一个else
语句。 CASE best_model_fit WHEN 'SUNNY' then dailywx.hoursabove4k_sunny ELSE -1 END applied_f_model_hours_above4k
-- 在 else 子句中使用您想要的任何值作为默认值。如果它的所有值都是空的,那么您可能没有正确的查询的其余部分,或者数据没有按照您的想法设置(例如,它不符合您的条件。)***.com/q/40101963/2084315
【参考方案1】:
在一个表中,所有行都有相同的列。您不能拥有仅存在于某些行的列。由于查询结果本质上是一个表,因此也适用于那里。
因此,对于信息不适用的行,将结果设为 NULL 或 0 是您唯一的选择。
CASE
表达式返回 NULL 的原因是您没有 ELSE
分支。如果 WHEN
条件都不适用,则结果为 NULL。
查询的性能是另一回事。您需要提供EXPLAIN (ANALYZE, BUFFERS)
输出来分析它。但是在加入大表时,将work_mem
设置得足够高通常是有益的。
【讨论】:
感谢@Laurenz Albe。我现在在两个语句上都更改为左连接,并将我的内存/缓存值设置为这个过程相当高(26GB),并注意到查询的显着加速。但是,我仍然对 case 语句返回 null 的原因感到困惑。 我已经添加了解释。以上是关于POSTGRESQL:使用连接表的案例的主要内容,如果未能解决你的问题,请参考以下文章
连接postgres特别消耗cpu资源而引发的PostgreSQL性能优化考虑
连接postgres特别消耗cpu资源而引发的PostgreSQL性能优化考虑
postgres数据库连接driver,url,username,password