Sql 查找表中符合条件的最右边的列

Sql 查找表中符合条件的最右边的列,sql,postgresql,Sql,Postgresql,我用Postgres创建了一个表,它统计电子邮件地址在层次结构的每个级别中出现的次数。层次结构的层次从左到右依次为:aka,区域汇总到品牌,区域汇总到区域,站点汇总到区域 我的目标是用电子邮件地址不同的最低层次结构级别的名称填充“Lower_distinct_level”列。下面是一个示例表: email_address | brand | region | area | site | lowest_distinct_level ----------------|-------|------

我用Postgres创建了一个表,它统计电子邮件地址在层次结构的每个级别中出现的次数。层次结构的层次从左到右依次为:aka,区域汇总到品牌,区域汇总到区域,站点汇总到区域

我的目标是用电子邮件地址不同的最低层次结构级别的名称填充“Lower_distinct_level”列。下面是一个示例表:

email_address   | brand | region | area | site | lowest_distinct_level
----------------|-------|--------|------|------|----------------------
alpha@gmail.com |   1   |    1   |   1  |   2  |
beta@gmail.com  |   1   |    1   |   2  |   0  |
gamma@gmail.com |   1   |    1   |   2  |   2  |
zeta@gmail.com  |   1   |    2   |   0  |   0  |
  • Alpha的电子邮件显示在两个站点中,但只有一个区域,所以最低级别应该用“区域”填充
  • Beta的电子邮件显示在两个区域,但只有一个区域,所以“区域”应该填充
  • Gamma的电子邮件出现在两个站点上,但这两个站点位于不同的区域。因此,“区域”应该被填充
  • 泽塔的一行应该是“品牌”

简而言之,对于每一行,我需要找到值为1的最右边的列,并将该列的名称作为值输出到最低的_distinct_级别。是否有一种相对有效的方法来使用PLPGSQL或阵列来实现这一点?一般来说,我不太擅长编写脚本或编码,因此如果这是一件小事,我深表歉意。

这是一个使用嵌套大小写的基本解决方案:

select email_address, brand, region, area, site,
    case when site = 1 then 'site'
         else case when area = 1 then 'area'
              else case when region = 1 then 'region'
                   else case when brand = 1 then 'brand'
                             else ''
                             end
                        end       
                   end
         end as lowest_distinct_level 
from mm;
结果是:

+-----------------+-------+--------+------+------+-----------------------+
| email_address   | brand | region | area | site | lowest_distinct_level |
+-----------------+-------+--------+------+------+-----------------------+
| alpha@gmail.com | 1     | 1      | 1    | 2    | area                  |
+-----------------+-------+--------+------+------+-----------------------+
| beta@gmail.com  | 1     | 1      | 2    | 0    | region                |
+-----------------+-------+--------+------+------+-----------------------+
| gamma@gmail.com | 1     | 1      | 2    | 2    | region                |
+-----------------+-------+--------+------+------+-----------------------+
| zeta@gmail.com  | 1     | 2      | 0    | 0    | brand                 |
+-----------------+-------+--------+------+------+-----------------------+
Abelisto写了一个简短的版本:

select email_address, brand, region, area, site,
    case when site = 1 then 'site'
         when area = 1 then 'area'
         when region = 1 then 'region'
         when brand = 1 then 'brand'
         else ''
    end as lowest_distinct_level
from mm;

选中此处:

这是使用嵌套大小写的基本解决方案:

select email_address, brand, region, area, site,
    case when site = 1 then 'site'
         else case when area = 1 then 'area'
              else case when region = 1 then 'region'
                   else case when brand = 1 then 'brand'
                             else ''
                             end
                        end       
                   end
         end as lowest_distinct_level 
from mm;
结果是:

+-----------------+-------+--------+------+------+-----------------------+
| email_address   | brand | region | area | site | lowest_distinct_level |
+-----------------+-------+--------+------+------+-----------------------+
| alpha@gmail.com | 1     | 1      | 1    | 2    | area                  |
+-----------------+-------+--------+------+------+-----------------------+
| beta@gmail.com  | 1     | 1      | 2    | 0    | region                |
+-----------------+-------+--------+------+------+-----------------------+
| gamma@gmail.com | 1     | 1      | 2    | 2    | region                |
+-----------------+-------+--------+------+------+-----------------------+
| zeta@gmail.com  | 1     | 2      | 0    | 0    | brand                 |
+-----------------+-------+--------+------+------+-----------------------+
Abelisto写了一个简短的版本:

select email_address, brand, region, area, site,
    case when site = 1 then 'site'
         when area = 1 then 'area'
         when region = 1 then 'region'
         when brand = 1 then 'brand'
         else ''
    end as lowest_distinct_level
from mm;

检查这里:

这确实可以用数组解决:

select *, 
       case array_position(array[site,area,region,brand],1)
         when 1 then 'site'
         when 2 then 'area'
         when 3 then 'region'
         else 'brand'
       end as lowest_distinct_level
from mm

这确实可以通过一个数组来解决:

select *, 
       case array_position(array[site,area,region,brand],1)
         when 1 then 'site'
         when 2 then 'area'
         when 3 then 'region'
         else 'brand'
       end as lowest_distinct_level
from mm

为什么您认为您需要一个存储函数?使用数组,它可以是
select…,(数组['site','area','region','brand'])[array\u position(数组[site,area,region,brand],1)],作为与…不同的最低级别。
如果行是1 2 1怎么办?您希望返回什么?您好,Gordon,由于层次结构文件的构造方式,无法返回1 2 1-一个站点不可能绑定到两个单独的区域。您认为为什么需要存储函数?使用数组,它可以是
select…,(数组['site','area','region','brand'])[array_position(数组[site,area,region,brand],1)作为与…不同的最低级别
如果行为1 2 1怎么办?你想要返回什么?嗨,Gordon,由于层次结构文件是如何构造的,所以无法返回1-一个站点不可能绑定到两个单独的区域。谢谢你的快速回答。我显然在运行一个旧版本的Postgres。。。我不知道数组位置是一个东西,因为它显然是在9.5中添加的,而我的计算机有9.3。我将安装9.6并尝试您编写的内容。对我来说,更大的挑战是使这个通用-适用于任何数量的层次结构字段。谢谢你的快速回答。我显然在运行一个旧版本的Postgres。。。我不知道数组位置是一个东西,因为它显然是在9.5中添加的,而我的计算机有9.3。我将安装9.6并尝试您编写的内容。对我来说,更大的挑战是使这个通用-适用于任何数量的层次结构字段。谢谢@McNets!这个案例陈述非常有效。我应该在主要问题中写下这一点,但要更详细地说明我在做什么——最终目标是以一种通用的方式,针对任意数量的层次结构列(和名称)。我想我可以构建一个函数,通过根据传入的参数生成更新脚本来动态工作。@flamewheel使用array_position和查找表,您可以轻松获得它。显然,我不能使用array_position-在另一条注释中解释了这一点,但服务器上运行的Postgres版本是9.3.9。数组_位置看起来像是在9.5中添加的。由于我不是DBA,我现在无法升级:(谢谢@McNets!case语句工作得很好。我应该在主要问题中写下这一点,但要更详细地说明我在做什么-最终目标是使这项工作以通用方式进行,适用于任意数量的层次结构列(和名称)。我想我可以构建一个函数,通过根据传入的参数生成更新脚本来动态工作。@flamewheel使用array_position和一个查找表,您可以轻松获得它。显然,我不能使用array_position-在另一个注释中解释了这一点,但服务器上运行的Postgres版本是9.3.9.array_的职位看起来像是在9.5中添加的。由于我不是DBA,所以目前无法升级:(