Regex 在行中计数非空列
我试图确定填充的特定列的数量,以下是我试图做的:Regex 在行中计数非空列,regex,postgresql,function,null,plpgsql,Regex,Postgresql,Function,Null,Plpgsql,我试图确定填充的特定列的数量,以下是我试图做的: foo := COALESCE($1.col1, '') || ' ' || COALESCE($1.col2, '') || ' ' || COALESCE($1.col3, '') || ' ' || COALESCE($1.col4, ''); foo := REPLACE(foo, var, ' '); words := string_to_array(foo, ' '); RETURN array
foo := COALESCE($1.col1, '') || ' ' ||
COALESCE($1.col2, '') || ' ' ||
COALESCE($1.col3, '') || ' ' ||
COALESCE($1.col4, '');
foo := REPLACE(foo, var, ' ');
words := string_to_array(foo, ' ');
RETURN array_length(words, 1);
如果
var
是空白,\s
似乎不起作用。我愿意使用任何其他方法来查找非nil列的数量。类似的方法会奏效,而且更容易
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:在Postgres9.3或更高版本中,您可以在不拼写所有列的情况下执行此操作,甚至不知道它们:
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\u each\u text()
默认情况下返回(键、值)
。如果命名冲突,请使用不同的别名和/或表限定名。如果您只对选定的列感兴趣,则可以在WHERE
子句中筛选列名
或者将附加模块用于相同目的,至少从Postgres8.3开始提供:
count()
不计算空值(也从不返回空值)。正是你需要的
您可以将其封装在函数中。具有多态输入类型的简单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($1))';
电话:
(重复使用比尔的设置)。以下表为例
| 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 ║
╚═════╩═════════╩═════════╩═════════╩═════════════╝
您的Postgres版本应始终声明。这显然是PL/pgSQL代码,也需要声明(否则只知道SQL的读者会感到困惑)。还有几个细节:我使用的是postgres 9.3.4.2,我正在计算的列只是从列中选择的几个列。出于性能原因,这必须是一个函数。是否仅为一组已知列运行它?或者,对于任何给定的行,都需要函数吗?相关列的数据类型是否始终相同?请更新您的问题以澄清。
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 ║
╚═════╩═════════╩═════════╩═════════╩═════════════╝