使用来自三层嵌套表的聚合列创建视图
Create view with aggregated columns from three levels of nested tables
我正在使用 Postgres 9.4,我有 3 个 tables:truck
、container
和 container_metadata
.
一个 truck
可以有很多 container
而一个 container
可以有很多 container_metadata
.
我稍后会在下面的 table 中添加更多描述(我已尽力创建它们),所以这里是:
一辆卡车可以装很多集装箱truck_id
一个容器然后由container_metadata
table描述,一个容器也可以有许多不同类型的记录,但在这种情况下,我将只关注'subcontainer'类型。
我要解决的问题是创建一个视图以便于查询和创建模型(用于数据浏览器)。我将在下面添加更多详细信息。
在最后一列中,如果卡车有:
,all good
为真
- 至少一个容器。
- 一个容器在元数据中应该至少有一个
subcontainer
类型的记录。
- 所有子容器的体积值应为正非零。
更多详情:
- 如果一辆卡车没有集装箱,那么我应该有一栏来描述我是否需要为它创建集装箱。
- 如果一辆卡车有集装箱但没有子集装箱,那么我应该也能知道我需要为它创建子集装箱记录。
- 如果一辆卡车有 10 个集装箱,但只有 6 个集装箱至少有一个子集装箱,那还是不行,我应该能看出我还需要创建一个子集装箱。
- 如果一辆卡车的集装箱有子集装箱,但是其中一个子集装箱的体积为0,同样,这不好,我也应该通知我们需要填充它。
我只能对容器、子容器进行计数我一直在尝试聚合函数,但我是这个问题的新手,希望 table 能有所帮助。请务必询问是否需要更多说明。
查询
我目前的尝试:
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
;
假设架构是 public。以上是我试过的查询,但它输出了错误数量的子容器,这就是我得到的结果。
假设 container_metadata.volume
为 NOT 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;
主要特点是先聚合,然后然后加入到下一个上层。无论如何,它不仅在处理大部分或全部 table 时通常更快,而且还允许一次性聚合每个级别:
- Why does the following join increase the query time significantly?
您需要非常小心 NULL
值可能会悄悄出现的地方。这些值可以通过列值或 LEFT JOIN
(缺失行)引入。因此,必须观察哪些列可以为 NULL。该查询仅与拟合 table 定义结合使用才有效。
当然,您需要了解 logical and comparison operators,尤其是涉及 NULL 值时。
聚合 FILTER
需要 Postgres 9.4:
- How can I simplify this game statistics query?
SQL Fiddle 没有数据,因为没有提供数据。所以也没有测试。
我正在使用 Postgres 9.4,我有 3 个 tables:truck
、container
和 container_metadata
.
一个 truck
可以有很多 container
而一个 container
可以有很多 container_metadata
.
我稍后会在下面的 table 中添加更多描述(我已尽力创建它们),所以这里是:
一辆卡车可以装很多集装箱truck_id
一个容器然后由container_metadata
table描述,一个容器也可以有许多不同类型的记录,但在这种情况下,我将只关注'subcontainer'类型。
我要解决的问题是创建一个视图以便于查询和创建模型(用于数据浏览器)。我将在下面添加更多详细信息。
在最后一列中,如果卡车有:
,all good
为真
- 至少一个容器。
- 一个容器在元数据中应该至少有一个
subcontainer
类型的记录。 - 所有子容器的体积值应为正非零。
更多详情:
- 如果一辆卡车没有集装箱,那么我应该有一栏来描述我是否需要为它创建集装箱。
- 如果一辆卡车有集装箱但没有子集装箱,那么我应该也能知道我需要为它创建子集装箱记录。
- 如果一辆卡车有 10 个集装箱,但只有 6 个集装箱至少有一个子集装箱,那还是不行,我应该能看出我还需要创建一个子集装箱。
- 如果一辆卡车的集装箱有子集装箱,但是其中一个子集装箱的体积为0,同样,这不好,我也应该通知我们需要填充它。
我只能对容器、子容器进行计数我一直在尝试聚合函数,但我是这个问题的新手,希望 table 能有所帮助。请务必询问是否需要更多说明。
查询
我目前的尝试:
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
;
假设架构是 public。以上是我试过的查询,但它输出了错误数量的子容器,这就是我得到的结果。
假设 container_metadata.volume
为 NOT 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;
主要特点是先聚合,然后然后加入到下一个上层。无论如何,它不仅在处理大部分或全部 table 时通常更快,而且还允许一次性聚合每个级别:
- Why does the following join increase the query time significantly?
您需要非常小心 NULL
值可能会悄悄出现的地方。这些值可以通过列值或 LEFT JOIN
(缺失行)引入。因此,必须观察哪些列可以为 NULL。该查询仅与拟合 table 定义结合使用才有效。
当然,您需要了解 logical and comparison operators,尤其是涉及 NULL 值时。
聚合 FILTER
需要 Postgres 9.4:
- How can I simplify this game statistics query?
SQL Fiddle 没有数据,因为没有提供数据。所以也没有测试。