大家好,我在try 从一个行值非零的表中获取列名时遇到了问题.以以下样本数据为例:

create table your_table
(
  XUUID VARCHAR(100), 
  COUNT1 INT,
  COUNT2 INT,
  COUNT3 INT,
  COUNT4 INT
); 

INSERT INTO your_table values 
('id1', 2, 3, 0, 0),
('id2', 0, 0, 1, 0),
('id3', 0, 0, 0, 0),
('id4', 3, 0, 0, 0)  

我希望结果的格式如下:

xuuid |  non_zero_col_agg    |
------|----------------------|
id1   | ['count1', 'count2'] |
id2   | ['count3']           |
id3   | []                   |
id4   | ['count1']           |

我try 使用以下javascript函数来实现这一点:

create or replace function labels(count1 INT, count2 INT, count3 INT, count4 INT)
    returns listagg
    language javascript 
    strict
    as
    $$
    var res = [];
    var dict = {
        'count1' : COUNT1,
        'count2' : COUNT2,
        'count3' : COUNT3,
        'count4' : COUNT4
    };
    for (var key in dictionary){
        if (dict[key] > 0) {
            res.push(key)
        }
    };
    return(res);
    $$
;

但它返回了以下错误:

有办法解决这个问题吗?解决方案可以作为函数,也可以不作为函数,我 Select 作为函数,因为我不知道使用常规SQL的方法.

谢谢

推荐答案

SQL的表达能力足以在没有UDF的情况下解决这种情况.

这里是一个用OBJECT_CONSTRUCT求解的例子.此解决方案是动态的,它可以接受行级别上存在的任意数量的"countX"列:

WITH cte AS (
  SELECT xuuid, OBJECT_CONSTRUCT(*) AS c
  FROM your_table
)
SELECT XUUID, ARRAY_AGG(CASE WHEN s.KEY LIKE 'COUNT%' 
                             AND TRY_CAST(s.VALUE::STRING AS INT) > 0 THEN s.key END)
FROM cte
,LATERAL FLATTEN(input => c) s
GROUP BY XUUID
ORDER BY XUUID;

输出:

enter image description here

Sql相关问答推荐

SQL—如何在搜索的元素之后和之前获取元素?

有没有一种正确的方法来利用SQL UNION来从三个潜在查询中 Select 最大值?

在Golang中管理数据库事务的简洁方法

基于多个字段删除Access中的重复记录,同时保留最低优先级

仅 for each 唯一ID返回一个元素,并仅返回最新连接的记录

按日期时间(不包括秒)连接表

在查询Oracle SQL中创建替代ID

来自按PostgreSQL分组的最小日期

用VB.NET在Dapper中实现MS Access数据库顺序透视

需要使用SQLite查询进行一些奇怪的时间转换

将 json 列键映射到第二个表中的匹配列值

PostgreSQL:从多个字段收集特定指标的最后一个条目

SQL的左连接在多对多关系情况下使用

Postgres数据库维护:基于GROUP BY删除旧记录

每个ID的SQL返回可能的最低级别及其值

基于字符串的SQL查询

正则表达式忽略特定数据部分的分隔符

如何仅在满足条件时才按顺序在 SQL 中计数?

Postgres 条件求和函数

使用 JSON_BUILD_OBJ 从 Postgres 返回 JSON