1

I'm trying to output and label a column total from a rollup.

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

The query works fine and generates a total as expected, but the column value that I would expect to be 'Total' shows up as [null].

There's a good chance it's probably some lack of understanding on my part, but then there's this that says that PostgreSQL's COALESCE is non-standard and makes me wonder if it's really me.

To quote:

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.

(Lovely explanation, right?)

I also ran across some information that indicates that COALESCE data types have to match, otherwise the function fails silently. (!)

I would expect the string literal 'Total' to be interpreted as a varchar, and column_1 is defined in the database as a varchar(12), but at this point I am not sure of much of anything, and any help would be most appreciated.

4

2 回答 2

4

问题是这样的:

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 值为 true 并赋值为 1;非 NULL 值被赋值为 0。这些是第一个,因为排序是升序的(默认情况下)。

于 2018-09-30T21:42:43.367 回答
1

我不是 POSTGRESQL 方面的专家,但我仍然可以提供一些见解。最简单的方法是简单地使用子查询:

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;
于 2018-09-30T21:13:48.977 回答