【问题标题】:a query to find duplicates but exclude set查找重复但排除集合的查询
【发布时间】:2013-05-19 17:45:00
【问题描述】:

我有一个包含以下列的表格

Emp_id
Work_date
element

我想要一个查询(以下查询的修改版本),如果上表中给定的 work_date 和员工 ID(GROUP BY EMP_ID 和 WORK_DATE)超过 1 行,它将返回一行。所以我写了这样的查询:

SELECT EMP_ID, WORK_DATE  FROM myTable
where WORK_DATE = :p_WorkDate
GROUP BY EMP_ID, WORK_DATE
HAVING COUNT (1) > 1

例如:

EMP_ID  WORK_DATE
1       1/1/2013
1       1/1/2013
2       1/1/2013

如果我通过 2013 年 1 月 1 日的 :p_WorkDate:,查询应返回如下:

1    1/1/2013

基本上,我试图通过 EMP_ID 和 WORK_DATE 查找是否有超过 1 行,但还有额外的要求 ELEMENT 列包含的内容 - 如果它包含来自集合 (element1 + element2) 或 (element3 + element4) 的值。

附加要求(以下)取决于列包含的元素(如果行具有集合中的值)。

1) 有 2 行具有相同的 emp_id 和 work_date,其中一个元素列是 element1,另一个元素列是 element2(一组 element1 和 element 2)

例如:

EMP_ID  WORK_DATE element
1   1/1/2013  element1
1   1/1/2013  element2

查询不应返回任何行,因为即使有两行,它也是一个集合(element1 和 elelement2)

2) 有 2 行具有相同的 emp_id 和 work_date,其中一个元素列是 element3,另一个元素列是 element4(一组 element3 和元素 4)

例如:

EMP_ID  WORK_DATE element
1   1/1/2013  element3
1   1/1/2013  element4      

查询不应返回任何行,因为即使有两行,它也是一个集合(元素 3 和元素 4)

3) 如果有 2 行具有相同的 emp_id 和 work_date 并且不是上述集合应该返回一行

例如:

EMP_ID  WORK_DATE element
1   1/1/2013  element1
1   1/1/2013  xxx   

(如果元素列有元素2而不是元素1,结果相同)

如果我通过 2013 年 1 月 1 日的 :p_WorkDate:,查询应返回如下:

1    1/1/2013

4) 如果emp_id 和work_date 相同的行超过2 行,则无论包含什么元素列,都应该返回一行。

例如:

EMP_ID  WORK_DATE element
1   1/1/2013  element1
1   1/1/2013  element2
1   1/1/2013 xxx

如果我通过 2013 年 1 月 1 日的 :p_WorkDate:,查询应返回如下:

2013 年 1 月 1 日


谢谢

【问题讨论】:

  • 这些集合对存储在哪里?另外,count(1) 通常是 count(*) —— count(1) 没有优势,它的非传统性是一个劣势。
  • @DavidAldridge - 对可以在查询中硬编码

标签: sql oracle oracle11g aggregation


【解决方案1】:

试一试……我想我的逻辑是正确的:

select
  emp_id,
  work_date
from (
  select
    emp_id,
    work_date,
    min(element) min_element,
    max(element) max_element,
    count(*) rows_counted
  from
    mytable
  where
    work_date = :p_workdate
  group by
    emp_id,
    work_date
  having
    count (*) > 1)
where
  rows_counted > 2 or
  (min_element,max_element) not in (select 'element1' el1, 'element2' el2 from dual union all
                                    select 'element3' el1, 'element4' el2 from dual)

【讨论】:

    【解决方案2】:

    这是一个 set-within-a-set 子查询的示例,您可以在 having 子句中完成所有工作:

    SELECT EMP_ID, WORK_DATE
    FROM myTable
    where WORK_DATE = :p_WorkDate
    GROUP BY EMP_ID, WORK_DATE
    HAVING sum(case when element not in ('element1', 'element2', 'element3', 'element4')
                    then 1 else 0
               end) > 0 or
           (sum(case when element in ('element1', 'element2') > 0 and
            sum(case when element in ('element3', 'element4') > 0
           )
    

    逻辑是。 having 语句中的第一个子句是关于不在这两个集合中的任何元素。如果有,则返回一行。

    第二个条件是两个集合中都有元素。在这种情况下,您也将返回一行。如果所有行都只有一组中的元素,那么就可以了。

    对于存在三行重复的情况,例如两个'element1' 和一个'element2',您的规则不明确。有了这个配方就可以了。希望您了解如何针对您的具体情况扩展 having 子句。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-29
      • 2014-02-10
      • 1970-01-01
      • 2020-07-13
      • 2013-04-08
      • 2019-03-19
      相关资源
      最近更新 更多