计算行中的非空列
Count not-null columns in row
我正在尝试确定填充的特定列的数量,这是我正在尝试执行的操作:
foo := COALESCE(.col1, '') || ' ' ||
COALESCE(.col2, '') || ' ' ||
COALESCE(.col3, '') || ' ' ||
COALESCE(.col4, '');
foo := REPLACE(foo, var, ' ');
words := string_to_array(foo, ' ');
RETURN array_length(words, 1);
其中var
是白色的space,\s
好像不行。我愿意接受任何其他查找非零列数的方法。
像这样的东西会起作用,而且更容易。
create table foo (
id integer primary key,
col1 text,
col2 text,
col3 text);
insert into foo values
(0, null, null, null),
(1, null, null, 'aa'),
(2, null, 'aa', 'bb'),
(3, 'aa', 'bb', 'cc');
select id,
case when col1 is null then 1 else 0 end +
case when col2 is null then 1 else 0 end +
case when col3 is null then 1 else 0 end as null_columns
from foo;
生产
0 3
1 2
2 1
3 0
SQL Fiddle: http://sqlfiddle.com/#!15/2ab3c/7/0
在 Postgres 9.3 或更高版本中使用 JSON functions,您无需拼出所有列 - 甚至不知道它们 - 即可做到这一点:
SELECT t.*, count(value)::int AS notnull_ct -- cast to int is optional
FROM tbl t, json_each_text(row_to_json(t)) -- implicit LATERAL join
-- WHERE key LIKE 'col%' -- optionally consider only selected columns
GROUP BY tbl_id; -- PK column
默认为 json_each_text()
returns (key, value)
。在命名冲突的情况下使用不同的别名和/或 table-qualify 名称。如果您只对选定的列感兴趣,则可以在 WHERE
子句中过滤列名。
或者使用附加模块 hstore 达到同样的目的,至少从 Postgres 8.3:
开始可用
- Key value pair in PostgreSQL
SELECT t.*, count(v)::int AS notnull_ct
FROM tbl t, svals(hstore(t)) v
GROUP BY tbl_id;
主要特点是 count()
不计算 NULL 值(也从不计算 returns NULL)。正是您所需要的。
你可以把它封装在一个函数中。具有多态输入类型的简单 SQL 函数可以完成这项工作:
CREATE OR REPLACE FUNCTION f_count_notnull_in_row(ANYELEMENT)
RETURNS int LANGUAGE sql IMMUTABLE AS
'SELECT count(value)::int
FROM json_each_text(row_to_json())';
致电:
SELECT *, f_count_notnull_in_row(t)
FROM tbl t;
SQL Fiddle(重复使用 Bill 的设置)。
考虑以 table 为例
| id | col1 | col2 | col3 |
|----|--------|--------|--------|
| 0 | (null) | (null) | (null) |
| 1 | (null) | (null) | aa |
| 2 | (null) | aa | bb |
| 3 | aa | bb | cc |
使用 unnest() 和 array() 获得所需的输出。
SELECT id,count(col) not_null_col_cnt
FROM (SELECT id,unnest(array [col1,col2,col3]) col
FROM foo
) t
GROUP BY id
ORDER BY id
结果:
| id | not_null_col_cnt |
|----|------------------|
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
您可以使用简单的转换:
SELECT id,
(col1 IS NULL)::int + (col2 IS NULL)::int + (col3 IS NULL)::int As null_number
FROM table_name;
输出:
╔═════╦═════════╦═════════╦═════════╦═════════════╗
║ id ║ col1 ║ col2 ║ col3 ║ null_number ║
╠═════╬═════════╬═════════╬═════════╬═════════════╣
║ 1 ║ a ║ b ║ c ║ 0 ║
║ 2 ║ a ║ b ║ (null) ║ 1 ║
║ 3 ║ a ║ (null) ║ (null) ║ 2 ║
║ 4 ║ (null) ║ (null) ║ (null) ║ 3 ║
╚═════╩═════════╩═════════╩═════════╩═════════════╝
我正在尝试确定填充的特定列的数量,这是我正在尝试执行的操作:
foo := COALESCE(.col1, '') || ' ' ||
COALESCE(.col2, '') || ' ' ||
COALESCE(.col3, '') || ' ' ||
COALESCE(.col4, '');
foo := REPLACE(foo, var, ' ');
words := string_to_array(foo, ' ');
RETURN array_length(words, 1);
其中var
是白色的space,\s
好像不行。我愿意接受任何其他查找非零列数的方法。
像这样的东西会起作用,而且更容易。
create table foo (
id integer primary key,
col1 text,
col2 text,
col3 text);
insert into foo values
(0, null, null, null),
(1, null, null, 'aa'),
(2, null, 'aa', 'bb'),
(3, 'aa', 'bb', 'cc');
select id,
case when col1 is null then 1 else 0 end +
case when col2 is null then 1 else 0 end +
case when col3 is null then 1 else 0 end as null_columns
from foo;
生产
0 3
1 2
2 1
3 0
SQL Fiddle: http://sqlfiddle.com/#!15/2ab3c/7/0
在 Postgres 9.3 或更高版本中使用 JSON functions,您无需拼出所有列 - 甚至不知道它们 - 即可做到这一点:
SELECT t.*, count(value)::int AS notnull_ct -- cast to int is optional
FROM tbl t, json_each_text(row_to_json(t)) -- implicit LATERAL join
-- WHERE key LIKE 'col%' -- optionally consider only selected columns
GROUP BY tbl_id; -- PK column
json_each_text()
returns (key, value)
。在命名冲突的情况下使用不同的别名和/或 table-qualify 名称。如果您只对选定的列感兴趣,则可以在 WHERE
子句中过滤列名。
或者使用附加模块 hstore 达到同样的目的,至少从 Postgres 8.3:
开始可用- Key value pair in PostgreSQL
SELECT t.*, count(v)::int AS notnull_ct
FROM tbl t, svals(hstore(t)) v
GROUP BY tbl_id;
主要特点是 count()
不计算 NULL 值(也从不计算 returns NULL)。正是您所需要的。
你可以把它封装在一个函数中。具有多态输入类型的简单 SQL 函数可以完成这项工作:
CREATE OR REPLACE FUNCTION f_count_notnull_in_row(ANYELEMENT)
RETURNS int LANGUAGE sql IMMUTABLE AS
'SELECT count(value)::int
FROM json_each_text(row_to_json())';
致电:
SELECT *, f_count_notnull_in_row(t)
FROM tbl t;
SQL Fiddle(重复使用 Bill 的设置)。
考虑以 table 为例
| id | col1 | col2 | col3 |
|----|--------|--------|--------|
| 0 | (null) | (null) | (null) |
| 1 | (null) | (null) | aa |
| 2 | (null) | aa | bb |
| 3 | aa | bb | cc |
使用 unnest() 和 array() 获得所需的输出。
SELECT id,count(col) not_null_col_cnt
FROM (SELECT id,unnest(array [col1,col2,col3]) col
FROM foo
) t
GROUP BY id
ORDER BY id
结果:
| id | not_null_col_cnt |
|----|------------------|
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
您可以使用简单的转换:
SELECT id,
(col1 IS NULL)::int + (col2 IS NULL)::int + (col3 IS NULL)::int As null_number
FROM table_name;
输出:
╔═════╦═════════╦═════════╦═════════╦═════════════╗
║ id ║ col1 ║ col2 ║ col3 ║ null_number ║
╠═════╬═════════╬═════════╬═════════╬═════════════╣
║ 1 ║ a ║ b ║ c ║ 0 ║
║ 2 ║ a ║ b ║ (null) ║ 1 ║
║ 3 ║ a ║ (null) ║ (null) ║ 2 ║
║ 4 ║ (null) ║ (null) ║ (null) ║ 3 ║
╚═════╩═════════╩═════════╩═════════╩═════════════╝