具有四列即属性的案例陈述

时间:2019-07-02 16:46:48

标签: sql oracle


我有一个值为“ 1”,“ 0”或“”的表。该表有四列:p,q,r和s。

我需要帮助来创建一个case语句,以在属性等于1时返回值。

enter image description here
对于ID 5,case语句应返回“ p s”。

对于ID 14,case语句应返回“ s”。

对于ID 33,case语句应返回'p r s'。依此类推。


 我是否需要提供一个包含所有可能组合的案例说明?还是有更简单的方法。以下是我到目前为止提出的内容。

case 
    when p = 1  and q =1 then "p q"
    when p = 1  and r =1 then "p r"
    when p = 1  and s =1 then "p s"
    when r = 1 then r 
    when q = 1 then q 
    when r = 1 then r 
    when s = 1 then s 
    else ''

 end

3 个答案:

答案 0 :(得分:2)

一个解决方案可能是使用每个属性的大小写返回正确的值,并用修剪将其包围以除去尾随空格。

with tbl(id, p, q, r, s) as (
  select 5,1,0,0,1 from dual union all
  select 14,0,0,0,1 from dual
)
select id,
       trim(regexp_replace(case p when 1 then 'p' end ||
       case q when 1 then 'q' end ||
       case r when 1 then 'r' end ||
       case s when 1 then 's' end, '(.)', '\1 '))
from tbl; 

真正的解决方案是修复数据库设计。该设计在技术上违反了Boyce-Codd的第四范式,因为它包含多个1个独立属性。应该将ID“具有”或“属于”属性p或q等事实分开。此设计应为3个表,即具有ID的主表,包含有关主ID可能具有的属性的信息(p,q,r或s)的查找表,以及在适当的地方将两者结合起来的关联表(假定ID)行可以具有多个属性,并且一个属性可以属于多个ID),这就是建模多对多关系的方法。

main_tbl        main_attr             attribute_lookup

ID col1 col2    main_id  attr_id      attr_id    attr_desc
5                     5  1                  1    p
14                    5  4                  2    q
                     14  4                  3    r
                                            4    s

然后,查询该模型以构建您的列表将很容易,如果属性描述发生更改(仅需更改1个位置),则易于维护等。

像这样从中选择:

select m.ID, m.col1, listagg(al.attr_desc, ' ') within group (order by al.attr_desc) as attr_desc
from main_tbl m
  join main_attr ma
    on m.ID = ma.main_id
    join attribute_lookup al
      on ma.attr_id = al.attr_id
group by m.id, m.col1; 

答案 1 :(得分:0)

您可以将串联与decode()函数一起使用

select id, decode(p,1,'p','')||decode(q,1,'q','')
         ||decode(r,1,'r','')||decode(s,1,'s','') as "String"
  from t;

Demo

如果字母之间需要空格,请考虑使用:

with t(id,p,q,r,s) as
(
 select 5,1,0,0,1  from dual union all
 select 14,0,0,0,1 from dual union all
 select 31,null,0,null,1 from dual union all
 select 33,1,0,1,1 from dual 
), t2 as
(
select id, decode(p,1,'p','')||decode(q,1,'q','')
         ||decode(r,1,'r','')||decode(s,1,'s','') as str
  from t
), t3 as
(
select id, substr(str,level,1) as str, level as lvl
  from t2
connect by level <= length(str)
    and prior id = id
    and prior sys_guid() is not null
)
select id, listagg(str,' ') within group (order by lvl) as "String"
  from t3
 group by id;

Demo

答案 2 :(得分:0)

我认为,将列用于关系是一种不好的做法。

您应该有两个表,一个表称为arts,另一个表名为map art,如下所示:

ID    -   ART
1     -   p
2     -   q
3     -   r
4     -   2
...

映射将您的基本ID映射到您的art-id,看起来像这样

MYID    - ARTID
5       - 1
5       - 4

之后,您应该使用oracles枢轴运算符。它更动态