带有字符串文字的 Postgresql COALESCE 不能按预期工作
Postgresql COALESCE with String Literals does not work as expected
我正在尝试从汇总中输出和标记列总计。
select coalesce(column_1, 'Total') as coalesced_value,
sum(column_2) as column_sum
from table
where yada yada
group by rollup(coalesced_value)
order by coalesced_value
查询工作正常并按预期生成总计,但我期望为 'Total' 的列值显示为 [null]。
这很有可能是我缺乏理解,但后来有这样的说法 PostgreSQL's COALESCE is non-standard 让我怀疑这是否真的是我。
引用:
COALESCE on row types
The spec defines COALESCE(X,Y) as a syntactic transformation to CASE WHEN X IS NOT NULL THEN X ELSE Y END (it leaves open the question of whether X is really evaluated twice by disallowing non-deterministic expressions or expressions with side effects in this context). A consequence of this is that the rather odd rules for null tests of row types are applied.
PostgreSQL applies only the "is not the null value" test to X. Accordingly, if X is a row value containing null columns, PostgreSQL will return X, while the spec would require returning Y.
(很好的解释,对吧?)
我还 运行 浏览了一些指示 COALESCE 数据类型必须匹配的信息,否则该函数将无提示地失败。 (!)
我希望字符串文字 'Total' 被解释为 varchar,而 column_1 在数据库中被定义为 varchar(12),但此时我不确定任何事情,任何帮助将不胜感激。
我不是 POSTGRE 专家SQL,但我仍然可以提供一些见解。最简单的方法是简单地使用子查询:
select coalesce(column_1,'Total') as coalesced_value
,column_sum
from
(
select column_1
,sum(column_2) as column_sum
from table
where yada yada
group by rollup(column_1)
) a
order by coalesced_value;
如果你想避免子查询,你应该可以使用GROUPING函数。我知道这适用于 Teradata SQL,但经过一些谷歌搜索后,它似乎也适用于 POSTGRESQL:
select case when grouping(column_1) = 1 then 'Total'
else column_1 end as grouping_value
,sum(column_2) as column_sum
from table
where yada yada
group by rollup(column_1)
order by grouping_value;
问题是这样的:
group by rollup(coalesced_value)
您在 应用 coalesce()
之后按值 进行分组。因此,rollup
然后生成 null
值。
相反,按数据中的列分组:
select coalesce(column_1, 'Total') as coalesced_value,
sum(column_2) as column_sum
from table
where yada yada
group by rollup(column_1)
order by (column_1 is null)::int, -- put the total at the end
coalesced_value;
这会按照您希望的方式对结果进行明确排序。没有它,结果将是你想要的(我认为)。第一部分 (column1 is null)::int
是一个转换为数字的布尔表达式。 Null 值为真并赋值为 1;非 NULL 值被赋予值 0。这些是第一个,因为排序是升序的(默认情况下)。
我正在尝试从汇总中输出和标记列总计。
select coalesce(column_1, 'Total') as coalesced_value,
sum(column_2) as column_sum
from table
where yada yada
group by rollup(coalesced_value)
order by coalesced_value
查询工作正常并按预期生成总计,但我期望为 'Total' 的列值显示为 [null]。
这很有可能是我缺乏理解,但后来有这样的说法 PostgreSQL's COALESCE is non-standard 让我怀疑这是否真的是我。
引用:
COALESCE on row types
The spec defines COALESCE(X,Y) as a syntactic transformation to CASE WHEN X IS NOT NULL THEN X ELSE Y END (it leaves open the question of whether X is really evaluated twice by disallowing non-deterministic expressions or expressions with side effects in this context). A consequence of this is that the rather odd rules for null tests of row types are applied. PostgreSQL applies only the "is not the null value" test to X. Accordingly, if X is a row value containing null columns, PostgreSQL will return X, while the spec would require returning Y.
(很好的解释,对吧?)
我还 运行 浏览了一些指示 COALESCE 数据类型必须匹配的信息,否则该函数将无提示地失败。 (!)
我希望字符串文字 'Total' 被解释为 varchar,而 column_1 在数据库中被定义为 varchar(12),但此时我不确定任何事情,任何帮助将不胜感激。
我不是 POSTGRE 专家SQL,但我仍然可以提供一些见解。最简单的方法是简单地使用子查询:
select coalesce(column_1,'Total') as coalesced_value
,column_sum
from
(
select column_1
,sum(column_2) as column_sum
from table
where yada yada
group by rollup(column_1)
) a
order by coalesced_value;
如果你想避免子查询,你应该可以使用GROUPING函数。我知道这适用于 Teradata SQL,但经过一些谷歌搜索后,它似乎也适用于 POSTGRESQL:
select case when grouping(column_1) = 1 then 'Total'
else column_1 end as grouping_value
,sum(column_2) as column_sum
from table
where yada yada
group by rollup(column_1)
order by grouping_value;
问题是这样的:
group by rollup(coalesced_value)
您在 应用 coalesce()
之后按值 进行分组。因此,rollup
然后生成 null
值。
相反,按数据中的列分组:
select coalesce(column_1, 'Total') as coalesced_value,
sum(column_2) as column_sum
from table
where yada yada
group by rollup(column_1)
order by (column_1 is null)::int, -- put the total at the end
coalesced_value;
这会按照您希望的方式对结果进行明确排序。没有它,结果将是你想要的(我认为)。第一部分 (column1 is null)::int
是一个转换为数字的布尔表达式。 Null 值为真并赋值为 1;非 NULL 值被赋予值 0。这些是第一个,因为排序是升序的(默认情况下)。