sql - 计算一行中为 NULL 的属性数

标签 sql postgresql count null plpgsql

我想在表中添加一个新列来记录每个元组(行)的值为空的属性的数量。如何使用 SQL 获取号码?

例如,如果一个元组是这样的:

Name | Age | Sex
-----+-----+-----
Blice| 100 | null

我想像这样更新元组:

Name | Age | Sex | nNULL
-----+-----+-----+--------
Blice| 100 | null|  1

此外,因为我正在编写一个 PL/pgSQL 函数并且表名是从参数中获得的,所以我事先不知道表的架构。这意味着我需要用输入表名更新表。有人知道怎么做吗?

最佳答案

可能无需拼写列。将列转为行并计数。

聚合函数 count(<expression>) 只计算非空值,而 count(*) 计算所有 行。计算多个列的 NULL 值的最短和最快的方法是 count(*) - count(col) ...

适用于任何 列数为any任何 表数据类型。

在 Postgres 9.3+ 中内置 JSON functions :

SELECT *, (SELECT count(*) - count(v)
           FROM json_each_text(row_to_json(t)) x(k,v)) AS ct_nulls
FROM   tbl t;

什么是 x(k,v)

json_each_text()返回一组包含两列的行。默认列名是 keyvaluemanual where I linked 中可以看出.我提供了表和列的别名,因此我们不必依赖默认名称。第二列名为 v .

或者,在至少 8.3 之后的任何 Postgres 版本中,附加模块 hstore 安装,甚至更短,更快:

SELECT *,  (SELECT count(*) - count(v) FROM svals(hstore(t)) v) AS ct_nulls
FROM   tbl t;

这个更简单的版本只返回一组单一的值。我只提供一个简单的别名 v , 自 Action 为表 列的别名。

由于附加列是功能相关,所以我认为根本不将其保留在表中。不如像上面演示的那样动态计算它,或者用 polymorphic 创建一个小函数目的输入类型:

CREATE OR REPLACE FUNCTION f_ct_nulls(_row anyelement)
  RETURNS int  LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
'SELECT (count(*) - count(v))::int FROM svals(hstore(_row)) v';

(PARALLEL SAFE 仅适用于 Postgres 9.6 或更高版本。)

然后:

SELECT *, f_ct_nulls(t) AS ct_nulls
FROM   tbl t;

你可以把它包装成一个 VIEW ...

db<> fiddle here - 展示所有
<子>旧sqlfiddle

这也应该回答你的第二个问题:

... the table name is obtained from argument, I don't know the schema of a table beforehand. That means I need to update the table with the input table name.

关于sql - 计算一行中为 NULL 的属性数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31444591/

相关文章:

ruby - 如何计算 Ruby 中数组中数组的数量?

mysql - 我的 MySQL 表上的索引会提高我的网站性能吗?

sql - 如何按联合结果排序?

java - Spring 数据按顺序获取映射对象

sql - 从一个表中获取月份列表,并从另一个表中计算每个月份的列表

sql - 为什么计数忽略分组依据

MySQL 字段列表中的未知列..仅出现在大写列中

mysql 从 $_GET 从另一个表中选择表

mysql - 识别 Group By 中的组

java - 如何在 @EmbeddedId 属性中使用 Hibernate 的 @Filter 注释