使用来自三个嵌套表级

时间:2015-04-24 03:02:52

标签: sql postgresql view left-join aggregate

我使用的是Postgres 9.4,我有3个表:truckcontainercontainer_metadata
truck可以包含多个containercontainer多个container_metadata

我稍后会在下表中添加更多说明(我尽力创建它们),所以这里有:

enter image description here

卡车可以包含许多由钥匙 truck_id

引用的集装箱

enter image description here enter image description here

容器然后由container_metadata表描述,容器也可以有许多不同类型的记录,但在这种情况下,我将只关注“

我试图解决的问题是创建一个视图,以便于查询和模型创建(用于数据库)。我将在下面添加更多详细信息。

enter image description here

在最后一栏中,all good如果卡车有:{/ p>,则为真

  • 至少一个容器。
  • 容器在元数据中应至少有一个类型为subcontainer的记录。
  • 所有子容器的卷值应为正非零。

更多详情:

  • 如果卡车没有容器,那么我应该有一个专栏来描述我是否需要为它创建容器。
  • 如果卡车有容器但没有子容器,那么我也应该能够告诉我需要为它创建子容器记录。
  • 如果一辆卡车有10个集装箱,但只有6个集装箱至少有一个集装箱,那么它仍然不好,我应该能够说明我还需要创建一个集装箱。
  • 如果卡车的集装箱有子集装箱,但其中一个集装箱的容积为0,那么它又不好,我还应该通知我们需要填充它。

我只能计算容器,子容器,我一直在尝试集合功能,但我对这个问题不熟悉,我希望这些表有所帮助。请问是否需要更多说明。

查询

到目前为止我的尝试:

select 
t.id,t.name, count(c.id) as container_count, count(cm.id) as subcontainer_count
from
    public.truck t
left join
    public.container c
on
    c.truck_id = t.id
left join
    public.container_metadata cm
on
    cm.container_id = c.id and type = 'subcontainer'
group by t.id
;

假设架构是公开的。以上是我尝试的查询,但它输出的子容器数量错误,而且我已经走了多远。

1 个答案:

答案 0 :(得分:1)

假设container_metadata.volumeNOT NULL DEFAULT 0,这应该完成整个工作:

SELECT t.id, t.name
     , COALESCE(c.cont_ct, 0)      AS cont_ct
     , COALESCE(c.sub_ct, 0)       AS sub_ct
     , COALESCE(c.empty_ct, 0)     AS empty_ct
     , c.truck_id IS NULL          AS cont_missing
     , c.sub_missing IS NOT FALSE  AS sub_missing
     ,(c.empty_ct = 0) IS NOT TRUE AS sub_needfill
     , c.empty_ct = 0 AND NOT c.sub_missing AS all_good
FROM   truck t
LEFT   JOIN (
   SELECT truck_id
        , count(*) AS cont_ct
        , sum(cm.ct_sub) AS sub_ct
        , sum(cm.ct_empty) AS empty_ct
        , bool_or(cm.container_id IS NULL) AS sub_missing
   FROM   container c
   LEFT JOIN (
      SELECT container_id
           , count(*) AS ct_sub
           , count(*) FILTER (WHERE volume = 0) AS ct_empty
      FROM   container_metadata
      WHERE  type = 'subcontainer'  -- only those seem relevant
      GROUP  BY 1
      ) cm ON cm.container_id = c.id
   GROUP  BY 1
   ) c ON c.truck_id = t.id;

主要功能是首先聚合,然后加入到下一个上一级。不仅在处理大部分或全部表格时它通常更快,它还允许一举聚合每个级别:

您需要非常小心NULL值可以进入的位置。这些值可以通过列值或LEFT JOIN(缺少的行)引入。因此,必须观察哪些列可以为NULL。该查询仅与拟合表定义一起有效。

当然,您需要了解logicalcomparison operators,特别是涉及NULL值。

汇总FILTER需要Postgres 9.4:

SQL Fiddle没有数据,因为没有提供数据。所以没有经过测试。