我有一个带有 N 列的表。让我们给他们打电话c1,c2,c3,c4,… cN。在多行中,我想为COUNTDISTINCT(cX)[1,N]中的每个X获得单个行。
c1
c2
c3
c4
cN
COUNTDISTINCT(cX)
c1 | c2 | ... | cn 0 | 4 | ... | 1
有没有一种方法(在存储过程中)而无需手动将每个列名写入查询中呢?
我们遇到了一个问题,即应用程序服务器中的错误意味着我们在以后插入垃圾时重写了良好的列值。为了解决这个问题,我存储了信息日志结构,其中每一行代表一个逻辑UPDATE查询。然后,在给出记录已完成的信号时,我可以确定是否有任何值(错误)被覆盖。
UPDATE
多行中的单个正确记录的示例:每列最多有一个值。
| id | initialize_time | start_time | end_time | | 1 | 12:00am | NULL | NULL | | 1 | 12:00am | 1:00pm | NULL | | 1 | 12:00am | NULL | 2:00pm | Reconciled row: | 1 | 12:00am | 1:00pm | 2:00pm |
我要检测的不可调和记录的示例:
| id | initialize_time | start_time | end_time | | 1 | 12:00am | NULL | NULL | | 1 | 12:00am | 1:00pm | NULL | | 1 | 9:00am | 1:00pm | 2:00pm | -- New initialize time => irreconcilable!
为此,您需要 动态SQL,这意味着您必须创建一个函数或运行一个DO命令。由于您不能直接从后者返回值,因此使用 plpgsql函数 是:
DO
CREATE OR REPLACE function f_count_all(_tbl text , OUT columns text[], OUT counts bigint[]) RETURNS record LANGUAGE plpgsql AS $func$ BEGIN EXECUTE ( SELECT 'SELECT ARRAY[' || string_agg('''' || quote_ident(attname) || '''', ', ') || '], ARRAY[' || string_agg('count(' || quote_ident(attname) || ')', ', ') || '] FROM ' || _tbl FROM pg_attribute WHERE attrelid = _tbl::regclass AND attnum >= 1 -- exclude tableoid & friends (neg. attnum) AND attisdropped is FALSE -- exclude deleted columns GROUP BY attrelid ) INTO columns, counts; END $func$;
称呼:
SELECT * FROM f_count_all('myschema.mytable');
返回值:
columns | counts --------------+-------- {c1, c2, c3,} | {17 1,0}