如何在相邻列中显示单独表的查询?

Ale*_*son 5 postgresql join datetime sum coalesce

我有两个表 - 一个标题为“计划约束”的表,其中包含“sot_allowed”时间间隔,另一个标题为“计划”,其中包含“sot_contribution”时间间隔。

以下是两个表的架构(为便于阅读而进行了编辑):

                         Table "public.planning_constraints"
   Column    |           Type           |          Modifiers  
-------------+--------------------------+-------------------------------
 start_time  | timestamp with time zone | 
 end_time    | timestamp with time zone | 
 sot_allowed | interval                 | 

                         Table "public.planning"
      Column      |           Type           |         Modifiers          
------------------+--------------------------+----------------------------
 start_time       | timestamp with time zone | 
 end_time         | timestamp with time zone | 
 sot_contribution | interval                 | 
Run Code Online (Sandbox Code Playgroud)

我可以分别查询它们并生成我想要的总数。“planning_constraints”表的查询是:

SELECT
  date_trunc('day', start_time - INTERVAL '18 hours')::date AS planning_day,
  sum(sot_allowed) AS minutes_allowed
FROM planning_constraints
WHERE start_time>='2016-11-26 18:00:00+00' AND start_time<'2016-12-03 18:00:00+00' AND comment like '6%'
GROUP BY planning_day
ORDER BY planning_day;
Run Code Online (Sandbox Code Playgroud)

它产生:

 planning_day | minutes_allowed 
--------------+-----------------
 2016-11-26   | 01:24:00
 2016-11-27   | 01:38:00
 2016-11-28   | 01:29:00
 2016-11-29   | 01:43:00
 2016-11-30   | 01:32:00
 2016-12-01   | 01:41:00
 2016-12-02   | 01:43:00
(7 rows)
Run Code Online (Sandbox Code Playgroud)

“计划”表的查询是:

SELECT
  date_trunc('day', start_time - INTERVAL '18 hours')::date AS planning_day,
  sum(sot_contribution) AS minutes_planned
FROM planning
WHERE start_time>='2016-11-26 18:00:00' AND start_time<'2016-12-03 18:00:00+00'
GROUP BY planning_day
ORDER BY planning_day;
Run Code Online (Sandbox Code Playgroud)

它产生:

 planning_day | minutes_planned 
--------------+-----------------
 2016-11-26   | 01:19:12
 2016-11-27   | 01:38:23
 2016-11-28   | 01:27:36
 2016-11-29   | 01:40:39
 2016-11-30   | 01:27:16
 2016-12-01   | 01:38:28
 2016-12-02   | 01:42:50
(7 rows)
Run Code Online (Sandbox Code Playgroud)

我想在相邻列中显示这些查询的结果,以及它们之间的差异。这是我这样做的尝试:

SELECT
  date_trunc('day', c.start_time - INTERVAL '18 hours')::date AS planning_day,
  sum(c.sot_allowed) AS minutes_allowed,
  sum(p.sot_contribution) AS minutes_planned,
  (sum(c.sot_allowed) - sum(p.sot_contribution)) AS diff
FROM planning_constraints c, planning p
WHERE c.start_time>='2016-11-26 18:00:00+00' AND c.start_time<'2016-12-03 18:00:00+00' AND c.comment like '6%'
AND p.start_time>='2016-11-26 18:00:00' AND p.start_time<'2016-12-03 18:00:00+00'
GROUP BY planning_day
ORDER BY planning_day;
Run Code Online (Sandbox Code Playgroud)

它产生:

 planning_day | minutes_allowed | minutes_planned |   diff    
--------------+-----------------+-----------------+-----------
 2016-11-26   | 576:48:00       | 43:37:36        | 533:10:24
 2016-11-27   | 672:56:00       | 43:37:36        | 629:18:24
 2016-11-28   | 611:08:00       | 43:37:36        | 567:30:24
 2016-11-29   | 707:16:00       | 43:37:36        | 663:38:24
 2016-11-30   | 631:44:00       | 43:37:36        | 588:06:24
 2016-12-01   | 693:32:00       | 43:37:36        | 649:54:24
 2016-12-02   | 707:16:00       | 43:37:36        | 663:38:24
(7 rows)
Run Code Online (Sandbox Code Playgroud)

'minutes_allowed' 和 'minutes_planned' 列没有提供正确的值。我觉得我在这里遗漏了一些小东西,但是,我一直无法找到解决方案。

dez*_*zso 5

您基本上是在构建两个表,然后必须将它们连接到日期列上。在您的查询中,您错过了连接条件。

解决此问题的一种明确方法是将两个结果集构建为 CTE(带查询):

WITH pc AS (SELECT planning_day, sum(sot_contribution) AS minutes_planned 
            FROM planning_constraints 
            ...),
      p AS (SELECT planning_day, sum(sot_allowed) AS minutes_allowed
            FROM planning
            ...)
SELECT planning_day, 
       COALESCE(minutes_allowed, interval '0 minute') AS allowed, 
       COALESCE(minutes_planned, interval '0 minute') AS planned, 
       COALESCE(minutes_allowed, interval '0 minute') - 
           COALESCE(minutes_planned, interval '0 minute') AS diff
  FROM pc FULL OUTER JOIN p USING (planning_day)
 ORDER BY planning_day;
Run Code Online (Sandbox Code Playgroud)

FULL OUTER JOIN意味着如果在任何一个结果集中指定了一天,那一天就会有一行。如果这不是您想要的,请弄清楚您需要哪种类型的连接

笔记:

  • planning_day不需要是COALESCEd,因为该USING条款会处理这个问题
  • 此外,不需要GROUP BY在外部查询中使用 a ,因为planning_day这已经是两个源表的键
  • ORDER BY可以从两个子查询现在删除