这实际上并不是一个交叉表作业(或其他RDBMS中的“枢轴”),但是如果您愿意,可以使用反向操作,即反交叉表。一个优雅的技术是LATERAL
连接中的VALUES
表达式。
基本查询可以是这样的,这需要的护理:
- 我不得不然后由值
转置结果和顺序
SELECT c.col, c.ct
FROM (
SELECT count(col1 OR NULL) AS col1
, count(col2 OR NULL) AS col2
-- etc.
FROM tbl
) t
, LATERAL (
VALUES ('col1', col1)
, ('col2', col2)
-- etc.
) c(col, ct)
ORDER BY 2
这是简单的部分。你的另外一个要求是很难:
- 我必须手动输入列
此功能需要你的表名,并从系统目录检索pg_attribute
元数据的名称。这是一个动态实现上述查询的,针对SQL注入安全:
CREATE OR REPLACE FUNCTION f_true_ct(_tbl regclass)
RETURNS TABLE (col text, ct bigint) AS
$func$
BEGIN
RETURN QUERY EXECUTE (
SELECT format('
SELECT c.col, c.ct
FROM (SELECT %s FROM tbl) t
, LATERAL (VALUES %s) c(col, ct)
ORDER BY 2 DESC'
, string_agg (format('count(%1$I OR NULL) AS %1$I', attname), ', ')
, string_agg (format('(%1$L, %1$I)', attname), ', ')
)
FROM pg_attribute
WHERE attrelid = _tbl -- valid, visible, legal table name
AND attnum >= 1 -- exclude tableoid & friends
AND NOT attisdropped -- exclude dropped columns
AND atttypid = 'bool'::regtype -- only character types
);
END
$func$ LANGUAGE plpgsql;
电话:
SELECT * FROM f_true_ct('tbl'); -- table name optionally schema-qualified
结果:
col | ct
------+---
col1 | 3
col3 | 2
col2 | 1
Works为任何表排名所有boolean
列的值为true
。有更多的解释
相关答案:
为了了解函数参数,请阅读此
可能'crosstab'会处理它。请提供http://sqlfiddle.com样本数据和期望的结果集 – lad2025
@ lad2025与'crosstab',您还必须手动输入列的名称。除非你使用动态声明,这与OP提供的方式基本相同(就结果而言) –
编辑你的问题并提供你想要的结果 –