如何在每列上执行相同的聚合,而不列出列?

And*_*ack 5 sql database postgresql relational-database

我有一个N列的表.让我们给他们打电话c1,c2,c3,c4,... cN.在多行中,我希望COUNT DISTINCT(cX)在[1,N]中为每个X 获得一行.

c1 | c2 | ... | cn
0  | 4  | ... | 1
Run Code Online (Sandbox Code Playgroud)

有没有办法我可以这样做(在存储过程中),而无需手动将每个列名写入查询?

为什么?

我们遇到了一个问题,即应用程序服务器中的错误意味着我们会在以后插入垃圾时重写好的列值.为了解决这个问题,我正在存储信息日志结构,其中每一行代表一个逻辑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   |
Run Code Online (Sandbox Code Playgroud)

我要检测的不可调和记录的示例:

| 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!
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 4

为此,您需要动态 SQLDO ,这意味着您必须创建一个函数或运行一个命令。由于您不能直接从后者返回值,因此它是一个plpgsql 函数:

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    NOT attisdropped       -- exclude deleted columns
       GROUP  BY attrelid
       )
   INTO columns, counts;
END
$func$;
Run Code Online (Sandbox Code Playgroud)

称呼:

SELECT * FROM f_count_all('myschema.mytable');
Run Code Online (Sandbox Code Playgroud)

返回:

columns       | counts
--------------+--------
{c1, c2, c3}  | {17, 1, 0}
Run Code Online (Sandbox Code Playgroud)

关于动态 SQL 的更多解释和链接以及EXECUTE这个相关问题- 或者更多关于 SO 的解释和链接,请尝试此搜索

有关的:

您甚至可以尝试返回多态记录类型以动态获取单个列,但这相当复杂和高级。对于您的情况来说可能需要付出太多努力。更多相关答案