【问题标题】:Combining two or more different SELECT queries to same table with different conditions in PostgreSQL在PostgreSQL中将两个或多个不同的SELECT查询组合到具有不同条件的同一张表中
【发布时间】:2020-01-02 12:08:22
【问题描述】:

我需要从同一个表中检索两个不同的结果,并将它们组合成一个结果集。我正在使用聚合函数来生成一些数据的报告,并且每一列都有不同的“位置”条件。

select sum(price) 
as lucro_esperado 
from tasks 
where extract(month from enddate) = 12 
AND extract(year from enddate) = 2019

select count(*) 
as tarefas_abertas 
from tasks 
where extract(month from date_added) = 12 
AND extract(year from date_added) = 2019

由于我对这种情况感兴趣的是聚合函数结果,因此我无法使用 Join 语句(因为没有 ON 条件),Union 语句会抱怨不同的数据类型,因为它试图错误地将两个聚合结果合并到一个列中。有没有其他方法可以实现这一点,而不必从我的 Node.js 端点查询数据库两次,然后手动组合它们?

【问题讨论】:

    标签: sql node.js postgresql express


    【解决方案1】:

    只需将其写为一个查询:

    select sum(price) as lucro_esperado, count(*) as tarefas_abertas
    from tasks
    where extract(month from enddate) = 12 and
          extract(year from enddate) = 2019
    

    我建议您将where 子句更改为:

    where enddate >= '2019-12-01' and
          enddate < '2020-01-01'
    

    这允许数据库使用enddate 上的索引(如果可用)。此外,删除列上的函数调用有助于优化器。

    编辑:

    我明白了,两个日期参数不同。只需使用条件聚合:

    select sum(case when enddate >= '2019-12-01' and enddate < '2020-01-01' then price end) as lucro_esperado,
           sum(case when date_added >= '2019-12-01' and date_added < '2020-01-01' then 1 else 0 end) as tarefas_abertas
    from tasks;
    

    【讨论】:

    • 我不能,因为我需要 sum(price) 来使用 enddate 参数(对于本月到期的付款)和 count(*) 来使用 date_added 参数(对于本月添加的任务) ,因为这两个列不一定总是在同一个月内(例如,在 11 月 28 日添加的任务,应在 12 月 15 日到期)
    • @RafaelOliveira 。 . .我懂了。这些是不同的日期。只需使用条件聚合。
    • 我完全不知道您在那里做了什么,先生,但工作就像一个魅力!非常感谢!
    【解决方案2】:

    使用聚合 FILTER 子句进行条件聚合。并保持count(*) 就像你拥有它一样。这样更短更快:

    SELECT sum(price) FILTER (WHERE enddate    >= '2019-12-01' AND enddate    < '2020-01-01') AS lucro_esperado
         , count(*)   FILTER (WHERE date_added >= '2019-12-01' AND date_added < '2020-01-01') AS tarefas_abertas
    FROM   tasks;
    

    相关:

    如果您在外部 WHERE 子句中重复条件超集以尽早消除行并充分利用索引,它通常会更快:

    SELECT sum(price) FILTER (WHERE enddate    >= '2019-12-01' AND enddate    < '2020-01-01') AS lucro_esperado
         , count(*)   FILTER (WHERE date_added >= '2019-12-01' AND date_added < '2020-01-01') AS tarefas_abertas
    FROM   tasks
    WHERE  enddate    >= '2019-12-01' AND enddate    < '2020-01-01'
    OR     date_added >= '2019-12-01' AND date_added < '2020-01-01';
    

    根据enddatedate_added 的实际数据类型,您可能需要调整输入以消除对会话当前时区设置的依赖。见:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-27
      • 2016-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多