0

I have a table with following columns

Emp_id
Work_date
element

I want a query (modified version of below query) which will return a single row if there are more than 1 row for given work_date and employee id (GROUP BY EMP_ID and WORK_DATE) in above table. So I have written query like:

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

For example:

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

Query should return as follows if I pass 1/1/2013 for :p_WorkDate:

1    1/1/2013

Basically I am trying to find if there are more than 1 row by EMP_ID and WORK_DATE but there is additional requirement what ELEMENT column contains - if it contains values from a set (element1 + element2) or (element3 + element4).

The additional requirements (following) depend upon what element column contains (if the rows have values from set).

1) There are 2 rows with same emp_id and work_date and one of the element column is element1 and other element column is element2 (a set of element1 and element 2)

For example:

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

the query should not return any row because even if there are two rows, it is a set (element1 and elelement2)

2) There are 2 rows with same emp_id and work_date and one of the element column is element3 and other element column is element4 (a set of element3 and element 4)

For example:

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

The query should not return any row because even if there are two rows, it is a set (element3 and element 4)

3) If there are 2 rows with same emp_id and work_date and which is not a set as above should return a row

For example:

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

(same result if element column had element2 instead of element1)

Query should return as follows if I pass 1/1/2013 for :p_WorkDate:

1    1/1/2013

4) If there are more than 2 rows with same emp_id and work_date, no matter what element column contains, it should return a row.

For example:

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

Query should return as follows if I pass 1/1/2013 for :p_WorkDate:

1 1/1/2013


Thank you

4

2 回答 2

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)
于 2013-05-19T18:20:55.800 回答
1

这是一个 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您的具体情况扩展该条款。

于 2013-05-19T18:38:46.257 回答