I'm trying to determine the number of specific columns that are populated, here's what I'm trying to do:
我要确定填充的特定列的数量,我要做的是:
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);
where var
is white space, \s
doesn't seem to work. I'm open to any other methods of finding the number of non-nil columns.
当var是空格时,\s似乎不起作用。我可以用任何其他方法来求非nil列的个数。
4 个解决方案
#1
1
You can do this without spelling out all columns - or even knowing about them - with JSON functions in Postgres 9.3 or later:
使用Postgres 9.3或更高版本的JSON函数,您可以不需要拼写出所有列,甚至不需要了解它们:
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
- What is the difference between LATERAL and a subquery in PostgreSQL?
- 在PostgreSQL中,横向和子查询的区别是什么?
json_each_text()
returns (key, value)
by default. Use different aliases and / or table-qualify names in case of naming conflicts. If you are only interested in selected columns, you can filter column names in a WHERE
clause.
json_each_text()默认返回(key, value)。在命名冲突时使用不同的别名和/或表限定名。如果您只对选定的列感兴趣,可以在WHERE子句中过滤列名称。
Or use the additional module hstore for the same purpose, available at least since Postgres 8.3:
或将额外的模块hstore用于相同的目的,至少从Postgres 8.3可以获得:
- Key value pair in PostgreSQL
- 在PostgreSQL中的键值对
SELECT t.*, count(v)::int AS notnull_ct
FROM tbl t, svals(hstore(t)) v
GROUP BY tbl_id;
The main feature is that count()
does not count NULL values (and never returns NULL either). Exactly what you need.
它的主要特性是count()不计算空值(也从不返回NULL)。正是你需要的。
You can encapsulate it in a function. A simple SQL function with a polymorphic input type does the job:
您可以将它封装在函数中。一个具有多态输入类型的简单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))';
Call:
电话:
SELECT *, f_count_notnull_in_row(t)
FROM tbl t;
SQL Fiddle (reusing Bill's setup).
SQL Fiddle(重用Bill的设置)。
#2
1
Something like this would work, and it's easier.
像这样的东西有用,而且更容易。
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;
Produces
生产
0 3
1 2
2 1
3 0
SQL Fiddle: http://sqlfiddle.com/#!15/2ab3c/7/0
SQL小提琴:http://sqlfiddle.com/ ! 15/2ab3c / 7/0
#3
0
Considering following table as an example
以下表为例
| id | col1 | col2 | col3 |
|----|--------|--------|--------|
| 0 | (null) | (null) | (null) |
| 1 | (null) | (null) | aa |
| 2 | (null) | aa | bb |
| 3 | aa | bb | cc |
Using unnest() and array() to get the desired output.
使用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
Result:
结果:
| id | not_null_col_cnt |
|----|------------------|
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
#4
0
You could use simple casting:
您可以使用简单的铸造:
SELECT id,
(col1 IS NULL)::int + (col2 IS NULL)::int + (col3 IS NULL)::int As null_number
FROM table_name;
SqlFiddleDemo
Output:
输出:
╔═════╦═════════╦═════════╦═════════╦═════════════╗
║ 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 ║
╚═════╩═════════╩═════════╩═════════╩═════════════╝
#1
1
You can do this without spelling out all columns - or even knowing about them - with JSON functions in Postgres 9.3 or later:
使用Postgres 9.3或更高版本的JSON函数,您可以不需要拼写出所有列,甚至不需要了解它们:
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
- What is the difference between LATERAL and a subquery in PostgreSQL?
- 在PostgreSQL中,横向和子查询的区别是什么?
json_each_text()
returns (key, value)
by default. Use different aliases and / or table-qualify names in case of naming conflicts. If you are only interested in selected columns, you can filter column names in a WHERE
clause.
json_each_text()默认返回(key, value)。在命名冲突时使用不同的别名和/或表限定名。如果您只对选定的列感兴趣,可以在WHERE子句中过滤列名称。
Or use the additional module hstore for the same purpose, available at least since Postgres 8.3:
或将额外的模块hstore用于相同的目的,至少从Postgres 8.3可以获得:
- Key value pair in PostgreSQL
- 在PostgreSQL中的键值对
SELECT t.*, count(v)::int AS notnull_ct
FROM tbl t, svals(hstore(t)) v
GROUP BY tbl_id;
The main feature is that count()
does not count NULL values (and never returns NULL either). Exactly what you need.
它的主要特性是count()不计算空值(也从不返回NULL)。正是你需要的。
You can encapsulate it in a function. A simple SQL function with a polymorphic input type does the job:
您可以将它封装在函数中。一个具有多态输入类型的简单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))';
Call:
电话:
SELECT *, f_count_notnull_in_row(t)
FROM tbl t;
SQL Fiddle (reusing Bill's setup).
SQL Fiddle(重用Bill的设置)。
#2
1
Something like this would work, and it's easier.
像这样的东西有用,而且更容易。
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;
Produces
生产
0 3
1 2
2 1
3 0
SQL Fiddle: http://sqlfiddle.com/#!15/2ab3c/7/0
SQL小提琴:http://sqlfiddle.com/ ! 15/2ab3c / 7/0
#3
0
Considering following table as an example
以下表为例
| id | col1 | col2 | col3 |
|----|--------|--------|--------|
| 0 | (null) | (null) | (null) |
| 1 | (null) | (null) | aa |
| 2 | (null) | aa | bb |
| 3 | aa | bb | cc |
Using unnest() and array() to get the desired output.
使用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
Result:
结果:
| id | not_null_col_cnt |
|----|------------------|
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
#4
0
You could use simple casting:
您可以使用简单的铸造:
SELECT id,
(col1 IS NULL)::int + (col2 IS NULL)::int + (col3 IS NULL)::int As null_number
FROM table_name;
SqlFiddleDemo
Output:
输出:
╔═════╦═════════╦═════════╦═════════╦═════════════╗
║ 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 ║
╚═════╩═════════╩═════════╩═════════╩═════════════╝