如何从一个表中组合多个选择查询

问题描述 投票:0回答:1

我想查询一个只有几列(例如下面的 4 列)的表,我想从中创建一个快照表,该表可以每天提供有关属性计数的见解

用户ID 属性1 属性2 属性3
1 真实 你好
2
3 你好
4
5 真实
6
7
8
9
10 你好

比如上面的

用户 ID 计数 属性名称 插入快照的日期
7 属性1 2024 年 4 月 16 日
6 属性2 2024 年 4 月 16 日
7 属性3 2024 年 4 月 16 日

在这种情况下,我们的原始表中可能有数百万行,超过 100 列,我们希望每天用每个属性具有非空值的用户计数和创建此快照的日期来填充快照表。

我的查询如下:-

select COUNT(DISTINCT userId) as userIdCount from orig_table where
    attr1 IS NOT NULL UNION Select COUNT(DISTINCT userId) as userIdCount
    from orig_table where attr2 IS NOT NULL UNION Select COUNT(DISTINCT
    userId) as userIdCount from orig_table where attr3 IS NOT NULL;

有没有一种优化的方法可以一起编写多个选择查询。我首先创建多个选择查询并将其一一插入到输出表中,但这似乎是一个不好的模式。请建议如何实现这一目标,以便可以扩展。

ps:新手(第一次探索数据库查询)

sql
1个回答
0
投票

我认为你的意思是

materialized view
。常规
view
会重新计算每个
select
上的查询,而
materialized view
会保留结果的快照,直到您
refresh
为止。

问题的多重选择部分可以使用PL/pgSQL块中的动态SQL来处理。

db<>fiddle 的演示:

do $f$
declare column_name_ text;
        dynamic_sql_query text;
        dynamic_sql_query_per_table text:=$$SELECT COUNT(DISTINCT "userId") AS %1$I
                                                 ,'%2$I' as "attrName"
                                                 ,now() AS "dateWhenSnapshotInserted"
                                           FROM orig_table 
                                           WHERE %2$I IS NOT NULL$$;
begin
for column_name_ in select column_name 
                    from information_schema.columns
                    where table_name='orig_table'
loop
    dynamic_sql_query:=concat_ws(' UNION ALL '
                                 ,dynamic_sql_query
                                 ,format( dynamic_sql_query_per_table
                                         ,column_name_||'Count'
                                         ,column_name_));
end loop;
execute format('CREATE MATERIALIZED VIEW orig_table_counts AS %s',dynamic_sql_query);
end $f$;

select * from orig_table_counts;
用户 ID 计数 属性名称 插入快照的日期
10 “用户ID” 2024-04-16 09:07:44.604273+00
7 属性1 2024-04-16 09:07:44.604273+00
6 属性2 2024-04-16 09:07:44.604273+00
7 属性3 2024-04-16 09:07:44.604273+00
© www.soinside.com 2019 - 2024. All rights reserved.