【问题标题】:To select text value from a group in sql从 sql 中的组中选择文本值
【发布时间】:2026-02-12 20:45:01
【问题描述】:

如果该组中存在该特定字符串,我想选择该行

我有一个包含 id 和 detail 列的表。

查询创建表:

create table emp_detail (id number,details varchar2(20));
insert into emp_detail values(12,'Major')
insert into emp_detail values(12,'Critical')
insert into emp_detail values(12,'high')
insert into emp_detail values(12,'Low')
insert into emp_detail values(13,'Major')
insert into emp_detail values(13,'Low')
insert into emp_detail values(13,'high')
insert into emp_detail values(14,'Critical')
insert into emp_detail values(14,'Low')
insert into emp_detail values(14,'high')

查询结果:

Id     Detail
12  Major
12  Critical
12  high
12  Low

13  Major
13  Low
13  high

14  Critical
14  Low
14  high

预期输出

Id     Detail
12  Critical
13  Major
14  Critical

因此,如果 id 的详细信息中同时存在关键和主要,那么我想选择仅关键。如果没有关键,则选择主要。如果只有关键,则将选择关键。

【问题讨论】:

    标签: sql oracle greatest-n-per-group


    【解决方案1】:

    这是一个优先级查询。你可以使用row_number():

    select id, details
    from (select ed.*,
                 row_number() over (partition by id
                                    order by (case details when 'Critical' then 1 when 'Major' then 2 when 'High' then 3 when 'Low' then 4 else 5
                                   ) as seqnum
          from emp_detail ed
         ) ed
    where seqnum = 1;
    

    您也可以使用join

    select id, details
    from (select ed.*,
                 row_number() over (partition by id
                                    order by d.ord nulls last
                                   ) as seqnum
          from emp_detail ed left join
               (select 'Critical' as details, 1 as ord from dual union all
                select 'Major' as details, 2 as ord from dual union all
                select 'High' as details, 3 as ord from dual union all
                select 'Low' as details, 4 as ord from dual union all
               ) d
               on ed.details = d.details
    
         ) ed
    where seqnum = 1;
    

    最后,解决此问题的一种有趣方法是使用聚合和coalesce()

    select id,
           coalesce( max(case when details = 'Critical' then details end),
                     max(case when details = 'Major' then details end),
                     max(case when details = 'High' then details end),
                     max(case when details = 'Low' then details end)
                   ) as details
    from emp_details ed
    group by id;
    

    注意:由于某种原因,'high' 不遵循您的大小写约定,因此请修复数据或使用'high' 进行上述查询。

    【讨论】:

      【解决方案2】:

      使用row_number()length()

      select id,detail from 
      (select id,detail,row_number() over(partition by id order by length(Detail) desc) rn
      from table_name
      ) a where a.rm=1
      

      【讨论】:

        【解决方案3】:

        试试这个-

        SELECT ID,
        CASE 
            WHEN Detail = 4 THEN 'Critical'
            WHEN Detail = 3 THEN 'Major'
            WHEN Detail = 2 THEN 'High'
            WHEN Detail = 1 THEN 'Low'
        END Detail
        FROM
        (
            SELECT ID,
            MAX(
            CASE 
                WHEN Detail = 'Critical' THEN 4
                WHEN Detail = 'Major' THEN 3
                WHEN Detail = 'High' THEN 2
                WHEN Detail = 'Low' THEN 1
            END Detail 
            )
            FROM your_table
            GROUP BY ID
        )A
        

        【讨论】:

          【解决方案4】:

          您可以使用MAX( details ) KEEP ( DENSE RANK FIRST ORDER BY ... ) 并使用CASE 语句设置排序首选项:

          Oracle 设置

          create table emp_detail (id, details ) AS
            SELECT 12, 'Major'    FROM DUAL UNION ALL
            SELECT 12, 'Critical' FROM DUAL UNION ALL
            SELECT 12, 'High'     FROM DUAL UNION ALL
            SELECT 12, 'Low'      FROM DUAL UNION ALL
            SELECT 13, 'Major'    FROM DUAL UNION ALL
            SELECT 13, 'High'     FROM DUAL UNION ALL
            SELECT 13, 'Low'      FROM DUAL UNION ALL
            SELECT 14, 'Critical' FROM DUAL UNION ALL
            SELECT 14, 'High'     FROM DUAL UNION ALL
            SELECT 14, 'Low'      FROM DUAL;
          

          查询

          SELECT id,
                 MAX( details )
                   KEEP (
                     DENSE_RANK FIRST
                     ORDER BY CASE details
                              WHEN 'Critical' THEN 1
                              WHEN 'Major'    THEN 2
                              WHEN 'High'     THEN 3
                              WHEN 'Low'      THEN 4
                                              ELSE 5
                              END
                   ) AS details
          FROM   emp_detail
          GROUP BY id
          

          输出

          身份证 |细节 -: | :-------- 12 |危急 13 |主要的 14 |危急

          db小提琴here

          【讨论】: