有没有一种方法可以返回给定行中的所有唯一值

时间:2019-11-27 14:03:05

标签: sql oracle

我正在使用Oracle SQL,并且具有带有这些标头的数据集
enter image description here
在此数据集中,卡号是唯一的,但是,客户可以在“建议”字段中重复输入。除了遍历和编写case语句,还有没有办法只在给定行中保留唯一值?

请注意,与其他客户相比,某些客户会得到更多“独特”的建议

例如: SAMPLE DATA

我的目标是使最终输出看起来像这样 enter image description here

正如我之前提到的,我只写案例声明说

SELECT DISTINCT CARD_NUMBER
    ,SUGGESTION_1
    ,CASE 
        WHEN SUGGESTION_2 != SUGGESTION_1
            THEN SUGGESTION_2
        WHEN SUGGESTION_3 != SUGGESTION_1
            THEN SUGGESTION_3
        WHEN SUGGESTION_4 != SUGGESTION_1
            THEN SUGGESTION_4
        WHEN SUGGESTION_5 != SUGGESTION_1
            THEN SUGGESTION_5
        END AS SUGGESTION_2 
    CASE 
        WHEN SUGGESTION_2 != SUGGESTION_1
            AND SUGGESTION_3 != SUGGESTION_1
            AND SUGGESTION_3 != SUGGESTION_2
            THEN SUGGESTION_3

`

我要这样做,直到剩下所有唯一的值,而且必须有一种更简单的方法 任何帮助将非常感谢,谢谢!

2 个答案:

答案 0 :(得分:1)

您可以使用union all和条件聚合。这是将结果放在单个列中的想法:

select card, listagg(suggestion, ', ') within group (order by which) as suggestions
from (select card, suggestion, min(which) as which
      from ((select card, 1 as which, suggestion_1 as suggestion from t) union all
            (select card, 2, suggestion_2 from t) union all
            (select card, 3, suggestion_3 from t) union all
            (select card, 4, suggestion_4 from t) union all
            (select card, 5, suggestion_5 from t)
           ) t
       group by card, suggestion
     ) t
group by card;

如果希望将值放在单独的列中,则可以对条件聚合执行类似的操作。

答案 1 :(得分:1)

我会尝试将表旋转到较长的位置,然后再回到宽的位置

设置:

create table testtbl
(
  CARD_NUMBER    int
  ,SUGGESTION_1  varchar2(100)
  ,SUGGESTION_2 varchar2(100)
  ,SUGGESTION_3 varchar2(100)
  ,SUGGESTION_4 varchar2(100)
  ,SUGGESTION_5 varchar2(100)

  );

insert into testtbl values (1234,'G11','G4','G3','G2','G6');
insert into testtbl values (5678,'G4','G6','G6','G11','G6');
insert into testtbl values (9101,'G1','G3','G11','G4','G11');

然后是查询本身,首先是轮换到long。在这里,我只使用一个函数来返回1到5之间的数字-而不是将表与自身连接5次,这样它就只能通过测试表一次。

然后我使用解析函数row_number根据唯一值的第一个位置对其进行排序。

第二个选择使用MAX旋转回宽

with cte AS
(
SELECT
    CARD_NUMBER
    ,MIN(n.column_value ) n
    ,CASE n.column_value 
        WHEN 1 THEN f.SUGGESTION_1
        WHEN 2 THEN f.SUGGESTION_2
        WHEN 3 THEN f.SUGGESTION_3
        WHEN 4 THEN f.SUGGESTION_4
        WHEN 5 THEN f.SUGGESTION_5
    END Suggestion
    ,ROW_NUMBER() OVER (PARTITION BY f.CARD_NUMBER ORDER BY MIN(n.column_value)) rn
FROM testtbl f
CROSS JOIN  table(sys.odcinumberlist(1,2,3,4,5)) n
GROUP BY f.CARD_NUMBER,CASE n.column_value 
        WHEN 1 THEN f.SUGGESTION_1
        WHEN 2 THEN f.SUGGESTION_2
        WHEN 3 THEN f.SUGGESTION_3
        WHEN 4 THEN f.SUGGESTION_4
        WHEN 5 THEN f.SUGGESTION_5
    END
)
SELECT 
CARD_NUMBER
,MAX(CASE WHEN rn=1 THEN Suggestion ELSE '' end)SUGGESTION_1
,MAX(CASE WHEN rn=2 THEN Suggestion ELSE '' end)SUGGESTION_2
,MAX(CASE WHEN rn=3 THEN Suggestion ELSE '' end)SUGGESTION_3
,MAX(CASE WHEN rn=4 THEN Suggestion ELSE '' end)SUGGESTION_4
,MAX(CASE WHEN rn=5 THEN Suggestion ELSE '' end)SUGGESTION_5
FROM cte
GROUP BY CARD_NUMBER
ORDER BY CARD_NUMBER