【问题标题】:Oracle 12c - select rows with multiple values in a groupOracle 12c - 在组中选择具有多个值的行
【发布时间】:2018-09-29 03:03:32
【问题描述】:
select ssn, count(*) 
from (
  select ssn, employee_id, is_active 
  from employee 
  where is_active ='Y'
)
group by ssn
having count(*) > 1

我想修改此查询以查找表中不止一次存在但具有不同employee_id 的所有ssn,其中至少一条记录具有is_active of Y。

【问题讨论】:

    标签: sql oracle oracle12c


    【解决方案1】:

    不需要子查询或 CTE,只需 group by 和 having:

    select ssn, count(*) 
    from employee
    group by ssn
    having min(employee_id) <> max(employee_id) and
           sum(case when is_active ='Y' then 1 else 0 end) >= 1;
    

    【讨论】:

      【解决方案2】:

      如果你想要所有的细节,那么:

      SELECT ssn,
             employee_id,
             is_active 
      FROM   (
        SELECT ssn,
               employee_id,
               is_active,
               COUNT( DISTINCT employee_id ) OVER ( PARTITION BY ssn ) AS num_emps,
               COUNT( CASE is_active WHEN 'Y' THEN 1 END ) OVER ( PARTITION BY ssn )
                 AS num_active
        FROM   employee
      )
      WHERE  num_emps > 1
      AND    num_active > 0
      

      如果你只想要ssns 那么:

      SELECT ssn
      FROM   employee
      GROUP BY ssn
      HAVING COUNT( DISTINCT employee_id ) > 1
      AND    COUNT( CASE is_active WHEN 'Y' THEN 1 END ) > 0;
      

      【讨论】:

        【解决方案3】:

        如果我理解正确,应该这样做

        select TMP.*
        from (
          select CASE WHEN MIN(employee_id) OVER( PARTITION BY ssn) <>
                           MAX(employee_id) OVER( PARTITION BY ssn) THEN 'Y'
                      ELSE 'N'
                  END AS hasMultipleDistinctEmployees,
                 CASE WHEN MAX(CASE WHEN is_active = 'Y' THEN 1 ELSE 0 END) OVER
                             ( PARTITION BY ssn ) = 1 THEN 'Y' 
                      ELSE 'N'
                  END AS hasAtLeaseOneActive,
          ssn, employee_id, is_active 
          from employee 
        ) TMP
        WHERE hasMultipleDistinctEmployees = 'Y'
          AND hasAtLeaseOneActive = 'Y'
        

        【讨论】:

          【解决方案4】:

          您可以使用窗口化的COUNT 来获取不同员工的数量,并使用SUM 来至少处理活动:

          WITH cte AS(
            select ssn, employee_id,
             COUNT(DISTINCT employee_id) OVER(PARTITION BY ssn) AS cnt,
             SUM(CASE WHEN is_active ='Y' THEN 1 ELSE 0 END) OVER(PARTITION BY ssn) AS s_active
            from employee 
          )
          SELECT *
          FROM cte
          WHERE cnt > 1 AND s_active > 1;
          

          【讨论】:

          • 这只会在有多个拥有不同employee_ids 的活跃员工时获得ssn
          • OP 说“至少有一个”具有不同 employee_id 的行必须具有 is_active = 'Y'。您的查询不会这样做 - 它至少会查找两行,包括 is_active = 'Y' 和不同的 employee_id。
          • 当然,HAVING 子句恰好存在,因此您不必像这样使用内部查询外部查询安排。
          • @mathguy 是的,但我想显示整行(ssn、employee_id、is_active)以显示完整图片而不是仅显示(ssn、count)
          • 了解,但 OP 想修改他的查询,即 select ssn, count(*)。不同的工具适用于不同的业务需求。
          猜你喜欢
          • 2019-03-26
          • 1970-01-01
          • 2021-07-17
          • 1970-01-01
          • 2015-10-17
          • 2021-07-30
          • 2021-05-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多