查询重复但查询排除的查询

时间:2013-05-19 17:45:01

标签: sql oracle oracle11g aggregation

我有一个包含以下列的表

Emp_id
Work_date
element

我想要一个查询(以下查询的修改版本),如果上表中给定的work_date和employee 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

如果我将1/1/2013传递给:p_WorkDate:

,则查询应返回如下
1    1/1/2013

基本上我试图通过EMP_ID和WORK_DATE查找是否有多于一行但是还有其他要求ELEMENT列包含的内容 - 如果它包含来自集合(element1 + element2)或(element3 + element4)的值。 / p>

附加要求(以下)取决于哪个元素列包含(如果行具有来自set的值)。

1)有两行具有相同的emp_id和work_date,其中一个元素列是element1,其他元素列是element2(一组element1和元素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      

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

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

例如:

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

(如果元素列具有element2而不是element1,则结果相同)

如果我将1/1/2013传递给:p_WorkDate:

,则查询应返回如下
1    1/1/2013

4)如果有超过2行具有相同的emp_id和work_date,则无论哪个元素列包含,它都应返回一行。

例如:

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

如果我将1/1/2013传递给:p_WorkDate:

,则查询应返回如下

1 1/1/2013


谢谢

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分:1)

这是一个set-within-set-sub子查询的示例,您可以在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子句。