SQL聚合函数选择唯一值

Tom*_*ský 5 sql postgresql aggregate unique aggregate-functions

我有一个包含两列的行集:technical_idnatural_id。行集实际上是复杂查询的结果。假定列中的值之间的映射是双射(即,对于两行相同technical_idnatural_ids为相同也为不同的technical_idS中的natural_ids为不同太)。(technical_id,natural_id)由于原始查询中的连接,这些对在行集中不是唯一的。例子:

with t (technical_id, natural_id, val) as (values
  (1, 'a', 1),
  (1, 'a', 2),
  (2, 'b', 3),
  (2, 'b', 2),
  (3, 'c', 0),
  (3, 'c', 1),
  (4, 'd', 1)
)
Run Code Online (Sandbox Code Playgroud)

不幸的是,双射仅由应用程序逻辑强制执行。的natural_id实际上是从多个表收集并使用由coalesce基于表达式,以便它的独特性几乎可以通过分贝约束来执行。

我需要通过technical_id假设natural_id是唯一的来聚合行集的行。如果不是(例如,如果将元组(4, 'x', 1)添加到示例数据中),则查询应该失败。在理想的 SQL 世界中,我会使用一些假设的聚合函数:

select technical_id, only(natural_id), sum(val)
from t
group by technical_id;
Run Code Online (Sandbox Code Playgroud)

我知道 SQL 中没有这样的功能。有什么替代方法或解决方法吗?Postgres 特定的解决方案也可以。

请注意,group by technical_id, natural_idor select technical_id, max(natural_id)- 尽管在愉快的情况下运行良好 - 都是不可接受的(首先是因为technical_id在所有情况下结果都必须是唯一的,其次是因为该值可能是随机的并掩盖了数据的不一致)。

感谢您的提示:-)

更新:预期的答案是

technical_id,v,sum
1,a,3
2,b,5
3,c,1
4,d,1
Run Code Online (Sandbox Code Playgroud)

或失败时4,x,1也存在。

Tom*_*ský 2

似乎我终于找到了基于 select 子句中相关子查询的单行基数的解决方案:

select technical_id,
       (select v from unnest(array_agg(distinct natural_id)) as u(v)) as natural_id,
       sum(val)
from t
group by technical_id;
Run Code Online (Sandbox Code Playgroud)

对于我目前的情况来说,这是最简单的解决方案,所以我将诉诸自我接受。无论如何,如果出现一些缺点,我会在这里描述它们并重新接受其他答案。我感谢所有其他建议,并相信它们对任何人都有价值。