首页 > 解决方案 > 如何将过滤器下推到视图的 group by 子句?

问题描述

我们在项目上有一个第三方 BI 工具,它只能where在表/视图选择上添加带有指定过滤器的子句。我们使用一组 4 个源表,它们具有可以使用 BI 的 UI 过滤的列的索引。我们为每个按索引列分组并添加 1 个附加列的表都有一个视图。然后我们有另一个视图,它使用索引列连接这 4 个视图中的所有数据,即从我们的 BI 的 UI 查询的视图,BIwhere向查询添加子句。

问题是没有使用源表上的索引,没有将过滤器推到表级别,而是在最后应用它们。我们不能使用 Set Returning Function,我们的 BI 工具只能从 table\view 中选择并添加一个where子句。

我们考虑过select在 Pg 中截取 a 的 where 条件,但我不确定这是否可能。或者,也许可以提示优化器需要下推过滤器。我们可以不使用视图直接查询源表,但它会在 UI 上增加许多数据源\元素,这是不可取的。有没有其他方法可以在 PostgreSQL 中解决它?

更新 1

下面是我们用于表和视图的模式/查询示例

CREATE TABLE source_table_1
(
  dim1                        VARCHAR(255) NOT NULL,
  dim2                        VARCHAR(255) NOT NULL,
  dim3                        VARCHAR(255) NOT NULL,
  meausre1                    Bigint       NOT NULL,
  meausre2                    Bigint       NOT NULL,
  meausre3                    Bigint       NOT NULL
);
CREATE INDEX ON uc13_failures_by_cell (dim1, dim2, dim3);

... another 3 tables

CREATE OR REPLACE VIEW view1 AS
SELECT 
      "type1" as type,
      dim1,
      dim2,
      dim3,
      sum(meausre1) AS meausre1,
      sum(meausre2) AS meausre2,
      sum(meausre3) AS meausre3
FROM source_table_1
GROUP BY 1, 2, 3, 4;

... another 3 views

CREATE OR REPLACE VIEW view_uinion AS
SELECT 
      coalesce(view1.dim1, view2.dim1, view3.dim1, view4.dim1) AS dim1,
      ... two other dims
      view1.meausre1             AS meausre1_1,
      view2.meausre1             AS meausre2_1,
      view3.meausre1             AS meausre3_1,
      view4.meausre1             AS meausre4_1,
      ... two meausres
FROM view1
         FULL JOIN view2 ON
            view1.dim1 = view2.dim1 AND
            view1.dim2 = view2.dim2 AND
            view1.dim3 = view2.dim3 AND
         FULL JOIN view3 ON ...
         FULL JOIN view4 ON ...
WHERE -- this is were filters on dims are inserted
;

标签: postgresql

解决方案


您不能将WHERE条件推送到完整的外部联接中。

看这个例子:

CREATE TABLE a(id integer NOT NULL, a1 integer NOT NULL);

INSERT INTO a VALUES (1, 20), (2, 20);

CREATE TABLE b(id integer NOT NULL, b1 integer NOT NULL);

INSERT INTO b VALUES (2, 30), (3, 30);

SELECT *
FROM a
   FULL JOIN b USING (id)
WHERE b1 = 30;

 id | a1 | b1 
----+----+----
  2 | 20 | 30
  3 |    | 30
(2 rows)

SELECT *
FROM a
   FULL JOIN (SELECT *
              FROM b
              WHERE b1 = 30) AS b_red
      USING (id);

 id | a1 | b1 
----+----+----
  1 | 20 |   
  2 | 20 | 30
  3 |    | 30
(3 rows)

所以你必须修改底层的查询/视图。

如果您使用内部联接,则不会有问题。


推荐阅读