计算行中的非空列

时间:2021-11-11 22:59:06

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

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可以获得:

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

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

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可以获得:

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

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 ║
╚═════╩═════════╩═════════╩═════════╩═════════════╝