PL/SQL 取幾段查詢結果的交集, 查詢費用報表的條件(R12.1.1)所對應的費用報表規則

The set operators UNION, UNION ALL, MINUS and INTERSECT combine the results of two queries. The two queries must have the same number of columns and the columns must be of the same data type family. Like join operations, set operations combine information from multiple tables. With a join operation, you combine these tables selecting columns from each table. With set operations, you combine these tables by selecting rows from each table.

Restrictions on set operators:

  • Set operators do not operate on columns of type BLOB, CLOB, BFILE, VARRAY or nested table. If you have nested tables, look instead at the MULTISET nested table functions.
  • Only UNION ALL will operate on columns of type LONG.
  • If you have an ORDER BY clause, you must either alias the expression you are ordering by, or use the column number syntax (e.g. ORDER BY 2).
  • You cannot specify FOR UPDATE in the same SQL statement with a set operator.

 

UNION ALL

UNION ALL is the most common set operator. It combines all of the rows from the first query with the rows from the second query. If we want to find the tables having a column named GRANTEE, we would run:

SELECT owner, table_name
  FROM dba_tab_columns
 WHERE column_name = 'GRANTEE'

47 rows

If we want to find the tables having a column named GRANTOR, we would run:

SELECT owner, table_name
  FROM dba_tab_columns
 WHERE column_name = 'GRANTOR'

29 rows

But if we want all of the tables that have EITHER a column called GRANTEE or GRANTOR, we would use the set operator UNION ALL.

SELECT owner, table_name
  FROM dba_tab_columns
 WHERE column_name = 'GRANTEE'
UNION ALL
SELECT owner, table_name
  FROM dba_tab_columns
 WHERE column_name = 'GRANTOR'

76 rows

The result set with the UNION ALL will have all of the rows from the top query as well as all of the rows from the bottom query and may contain duplicate records – some tables contain both a GRANTEE and a GRANTOR column. If we don’t want the duplicates in the result, we can use the UNION operator, which will sort the result set and eliminate duplicates.

UNION

The UNION operator is just like the UNION ALL operator, except that it will sort the results to eliminate duplicates. If you don’t need the duplicates eliminated, use the UNION ALL, eliminate the sorting operation and let your program run faster. In our example, we only want the tables to appear in the result set only once if they have either a GRANTEE or a GRANTOR. Using the UNION operator, we find that there are 51 tables, not 76. Hmm… we probably have 25 tables with both columns, but we’ll get to that shortly:

SELECT owner, table_name
  FROM dba_tab_columns
 WHERE column_name = 'GRANTEE'
UNION
SELECT owner, table_name
  FROM dba_tab_columns
 WHERE column_name = 'GRANTOR'

51 rows

 

Should I use UNION or UNION ALL?

There are times when you as a programmer want to eliminate duplicates and times when you don’t need to eliminate the dupes. A approach to take is to first consider UNION ALL, and if the possible duplicates will pose logic problems, then switch to UNION. Here are two examples to help clarify. In this first example, we are looking for tables that match our criteria:

WHERE (ownr, tabl) IN (SELECT owner, table_name
                         FROM dba_tab_columns
                        WHERE column_name = 'GRANTEE'
                       UNION ALL
                       SELECT owner, table_name
                         FROM dba_tab_columns
                        WHERE column_name = 'GRANTOR')

You should probably specify UNION ALL, and save a potentially costly sort in the sub query. Oracle will compare the ownr and tabl values to those in the subquery stopping when the first match is found (the predicate will evaluate to TRUE). There is no need to eliminate the duplicates, the processing logic will not change.

If on the other had your set query is driving some other iterative operation, for example:

FOR tabl_rec IN (SELECT owner, table_name
                   FROM dba_tab_columns
                  WHERE column_name = 'GRANTEE'
                 UNION
                 SELECT owner, table_name
                   FROM dba_tab_columns
                  WHERE column_name = 'GRANTOR')
LOOP
   process_record(tabl_rec);
END LOOP;

You should probably specify UNION, so you don’t process the same table twice.

MINUS

The MINUS operator combines the results from two queries by returning only those rows that appear in the top query and do not also appear in the bottom query. MINUS automatically sorts the results, eliminating duplicates. If we want the names of tables that have a GRANTEE column, but do not have a GRANTOR column, we would run the following:

SELECT owner, table_name
  FROM dba_tab_columns
 WHERE column_name = 'GRANTEE'
MINUS
SELECT owner, table_name
  FROM dba_tab_columns
 WHERE column_name = 'GRANTOR'

22 rows

 

INTERSECT

The INTERSECT operator combines the results from two queries by returning only those rows that appear both in the top query and the bottom query. INTERSECT automatically sorts the results, eliminating duplicates. So, to see those tables that have both a GRANTEE and a GRANTOR column we run:

SELECT owner, table_name
  FROM dba_tab_columns
 WHERE column_name = 'GRANTEE'
INTERSECT
SELECT owner, table_name
  FROM dba_tab_columns
 WHERE column_name = 'GRANTOR'

25 rows


 

---總部正常費用計財部審批規則5000以下
-----------

--規則明細
select DESCRIPTION
from (SELECT distinct arv.DESCRIPTION
FROM (select AmeConditionUsageEO.rule_id,
AmeConditionUsageEO.condition_id,
AmeConditionUsageEO.object_version_number,
AmeConditionUsageEO.start_date,
AmeConditionUsageEO.end_date,
ame_utility_pkg.get_condition_description(cond.condition_id) as DESCRIPTION,
condition_type_lookup.meaning as CONDITION_TYPE,
ic.user_item_class_name as ITEM_CLASS,
cond.condition_type as CONDITION_TYPE_CODE,
'CASE1' as CASE1,
'CASE3' as CASE2,
'DE' as DELETE_SWITCHER,
approver_order_lookup.meaning as APPROVER_ORDER,
ame_approver_type_pkg.getApproverDescription(cond.parameter_two) as APPROVER,
ic.item_class_id,
cond.parameter_one as APPROVER_ORDER_CODE
from ame_condition_usages AmeConditionUsageEO,
fnd_lookups condition_type_lookup,
(select *
from fnd_lookups
where lookup_type = 'AME_APPROVER_ORDER'
and enabled_flag = 'Y') approver_order_lookup,
ame_conditions cond,
wf_roles wf,
(select *
from ame_attributes_vl
where sysdate between start_date and
nvl(end_date - (1 / 86400), sysdate)) atr,
(select *
from ame_item_classes_vl
where sysdate between start_date and
nvl(end_date - (1 / 86400), sysdate)) ic
where ((sysdate between AmeConditionUsageEO.start_date and
nvl(AmeConditionUsageEO.end_date - (1 / 86400),
sysdate)) or
(sysdate < AmeConditionUsageEO.start_date and
AmeConditionUsageEO.start_date <
nvl(AmeConditionUsageEO.end_date,
AmeConditionUsageEO.start_date + (1 / 86400))))
and sysdate between cond.start_date and
nvl(cond.end_date - (1 / 86400), sysdate)
and cond.condition_id = AmeConditionUsageEO.condition_id
and cond.attribute_id = atr.attribute_id(+)
and nvl(atr.item_class_id, -99) = ic.item_class_id(+)
and condition_type_lookup.lookup_type =
'AME_CONDITION_TYPE'
and condition_type_lookup.enabled_flag = 'Y'
and condition_type_lookup.lookup_code =
upper(cond.condition_type)
and upper(cond.parameter_one) =
approver_order_lookup.lookup_code(+)
and cond.parameter_two = wf.name(+)) QRSLT,
AME_RULES_VL arv
WHERE (QRSLT.RULE_ID > 0 and QRSLT.CONDITION_TYPE_CODE <> 'post')
and arv.RULE_ID = qrslt.rule_id
and (QRSLT.description like '%EXPENSE_REPORT_TOTAL%less%5000%' OR
(QRSLT.description like '%EXPENSE_REPORT_TEMPLATE%10027%') OR
QRSLT.description like '%BOCD_OIE_COMPANY%0108%' OR
QRSLT.description like '%EXPENSE_REPORT_TOTAL%less%5000%'))
---EXPENSE_REPORT_TOTAL is less than or equal to 5000,CNY

INTERSECT (

select DESCRIPTION
from (SELECT distinct arv.DESCRIPTION
FROM (select AmeConditionUsageEO.rule_id,
AmeConditionUsageEO.condition_id,
AmeConditionUsageEO.object_version_number,
AmeConditionUsageEO.start_date,
AmeConditionUsageEO.end_date,
ame_utility_pkg.get_condition_description(cond.condition_id) as DESCRIPTION,
condition_type_lookup.meaning as CONDITION_TYPE,
ic.user_item_class_name as ITEM_CLASS,
cond.condition_type as CONDITION_TYPE_CODE,
'CASE1' as CASE1,
'CASE3' as CASE2,
'DE' as DELETE_SWITCHER,
approver_order_lookup.meaning as APPROVER_ORDER,
ame_approver_type_pkg.getApproverDescription(cond.parameter_two) as APPROVER,
ic.item_class_id,
cond.parameter_one as APPROVER_ORDER_CODE
from ame_condition_usages AmeConditionUsageEO,
fnd_lookups condition_type_lookup,
(select *
from fnd_lookups
where lookup_type = 'AME_APPROVER_ORDER'
and enabled_flag = 'Y') approver_order_lookup,
ame_conditions cond,
wf_roles wf,
(select *
from ame_attributes_vl
where sysdate between start_date and
nvl(end_date - (1 / 86400), sysdate)) atr,
(select *
from ame_item_classes_vl
where sysdate between start_date and
nvl(end_date - (1 / 86400), sysdate)) ic
where ((sysdate between AmeConditionUsageEO.start_date and
nvl(AmeConditionUsageEO.end_date - (1 / 86400),
sysdate)) or
(sysdate < AmeConditionUsageEO.start_date and
AmeConditionUsageEO.start_date <
nvl(AmeConditionUsageEO.end_date,
AmeConditionUsageEO.start_date + (1 / 86400))))
and sysdate between cond.start_date and
nvl(cond.end_date - (1 / 86400), sysdate)
and cond.condition_id =
AmeConditionUsageEO.condition_id
and cond.attribute_id = atr.attribute_id(+)
and nvl(atr.item_class_id, -99) = ic.item_class_id(+)
and condition_type_lookup.lookup_type =
'AME_CONDITION_TYPE'
and condition_type_lookup.enabled_flag = 'Y'
and condition_type_lookup.lookup_code =
upper(cond.condition_type)
and upper(cond.parameter_one) =
approver_order_lookup.lookup_code(+)
and cond.parameter_two = wf.name(+)) QRSLT,
AME_RULES_VL arv
WHERE (QRSLT.RULE_ID > 0 and
QRSLT.CONDITION_TYPE_CODE <> 'post')
and arv.RULE_ID = qrslt.rule_id
and (QRSLT.description like
'%EXPENSE_REPORT_TEMPLATE%10027%') --ap_expense_report_headers_all.expense_report_id
))
INTERSECT (

--規則明細
select DESCRIPTION
from (SELECT distinct arv.DESCRIPTION
FROM (select AmeConditionUsageEO.rule_id,
AmeConditionUsageEO.condition_id,
AmeConditionUsageEO.object_version_number,
AmeConditionUsageEO.start_date,
AmeConditionUsageEO.end_date,
ame_utility_pkg.get_condition_description(cond.condition_id) as DESCRIPTION,
condition_type_lookup.meaning as CONDITION_TYPE,
ic.user_item_class_name as ITEM_CLASS,
cond.condition_type as CONDITION_TYPE_CODE,
'CASE1' as CASE1,
'CASE3' as CASE2,
'DE' as DELETE_SWITCHER,
approver_order_lookup.meaning as APPROVER_ORDER,
ame_approver_type_pkg.getApproverDescription(cond.parameter_two) as APPROVER,
ic.item_class_id,
cond.parameter_one as APPROVER_ORDER_CODE
from ame_condition_usages AmeConditionUsageEO,
fnd_lookups condition_type_lookup,
(select *
from fnd_lookups
where lookup_type = 'AME_APPROVER_ORDER'
and enabled_flag = 'Y') approver_order_lookup,
ame_conditions cond,
wf_roles wf,
(select *
from ame_attributes_vl
where sysdate between start_date and
nvl(end_date - (1 / 86400), sysdate)) atr,
(select *
from ame_item_classes_vl
where sysdate between start_date and
nvl(end_date - (1 / 86400), sysdate)) ic
where ((sysdate between AmeConditionUsageEO.start_date and
nvl(AmeConditionUsageEO.end_date - (1 / 86400),
sysdate)) or
(sysdate < AmeConditionUsageEO.start_date and
AmeConditionUsageEO.start_date <
nvl(AmeConditionUsageEO.end_date,
AmeConditionUsageEO.start_date + (1 / 86400))))
and sysdate between cond.start_date and
nvl(cond.end_date - (1 / 86400), sysdate)
and cond.condition_id =
AmeConditionUsageEO.condition_id
and cond.attribute_id = atr.attribute_id(+)
and nvl(atr.item_class_id, -99) = ic.item_class_id(+)
and condition_type_lookup.lookup_type =
'AME_CONDITION_TYPE'
and condition_type_lookup.enabled_flag = 'Y'
and condition_type_lookup.lookup_code =
upper(cond.condition_type)
and upper(cond.parameter_one) =
approver_order_lookup.lookup_code(+)
and cond.parameter_two = wf.name(+)) QRSLT,
AME_RULES_VL arv
WHERE (QRSLT.RULE_ID > 0 and
QRSLT.CONDITION_TYPE_CODE <> 'post')
and arv.RULE_ID = qrslt.rule_id
--and (QRSLT.description like '%EXPENSE_REPORT_TEMPLATE%10027%')

and QRSLT.description like '%ORG_ID%121%'))

INTERSECT (

--規則明細
select DESCRIPTION
from (SELECT distinct arv.DESCRIPTION
FROM (select AmeConditionUsageEO.rule_id,
AmeConditionUsageEO.condition_id,
AmeConditionUsageEO.object_version_number,
AmeConditionUsageEO.start_date,
AmeConditionUsageEO.end_date,
ame_utility_pkg.get_condition_description(cond.condition_id) as DESCRIPTION,
condition_type_lookup.meaning as CONDITION_TYPE,
ic.user_item_class_name as ITEM_CLASS,
cond.condition_type as CONDITION_TYPE_CODE,
'CASE1' as CASE1,
'CASE3' as CASE2,
'DE' as DELETE_SWITCHER,
approver_order_lookup.meaning as APPROVER_ORDER,
ame_approver_type_pkg.getApproverDescription(cond.parameter_two) as APPROVER,
ic.item_class_id,
cond.parameter_one as APPROVER_ORDER_CODE
from ame_condition_usages AmeConditionUsageEO,
fnd_lookups condition_type_lookup,
(select *
from fnd_lookups
where lookup_type = 'AME_APPROVER_ORDER'
and enabled_flag = 'Y') approver_order_lookup,
ame_conditions cond,
wf_roles wf,
(select *
from ame_attributes_vl
where sysdate between start_date and
nvl(end_date - (1 / 86400), sysdate)) atr,
(select *
from ame_item_classes_vl
where sysdate between start_date and
nvl(end_date - (1 / 86400), sysdate)) ic
where ((sysdate between AmeConditionUsageEO.start_date and
nvl(AmeConditionUsageEO.end_date - (1 / 86400),
sysdate)) or
(sysdate < AmeConditionUsageEO.start_date and
AmeConditionUsageEO.start_date <
nvl(AmeConditionUsageEO.end_date,
AmeConditionUsageEO.start_date + (1 / 86400))))
and sysdate between cond.start_date and
nvl(cond.end_date - (1 / 86400), sysdate)
and cond.condition_id =
AmeConditionUsageEO.condition_id
and cond.attribute_id = atr.attribute_id(+)
and nvl(atr.item_class_id, -99) = ic.item_class_id(+)
and condition_type_lookup.lookup_type =
'AME_CONDITION_TYPE'
and condition_type_lookup.enabled_flag = 'Y'
and condition_type_lookup.lookup_code =
upper(cond.condition_type)
and upper(cond.parameter_one) =
approver_order_lookup.lookup_code(+)
and cond.parameter_two = wf.name(+)) QRSLT,
AME_RULES_VL arv
WHERE (QRSLT.RULE_ID > 0 and
QRSLT.CONDITION_TYPE_CODE <> 'post')
and arv.RULE_ID = qrslt.rule_id
and QRSLT.description like '%BOCD_OIE_COMPANY%0108%'))

INTERSECT (

--規則明細
select DESCRIPTION
from (SELECT distinct arv.DESCRIPTION
FROM (select AmeConditionUsageEO.rule_id,
AmeConditionUsageEO.condition_id,
AmeConditionUsageEO.object_version_number,
AmeConditionUsageEO.start_date,
AmeConditionUsageEO.end_date,
ame_utility_pkg.get_condition_description(cond.condition_id) as DESCRIPTION,
condition_type_lookup.meaning as CONDITION_TYPE,
ic.user_item_class_name as ITEM_CLASS,
cond.condition_type as CONDITION_TYPE_CODE,
'CASE1' as CASE1,
'CASE3' as CASE2,
'DE' as DELETE_SWITCHER,
approver_order_lookup.meaning as APPROVER_ORDER,
ame_approver_type_pkg.getApproverDescription(cond.parameter_two) as APPROVER,
ic.item_class_id,
cond.parameter_one as APPROVER_ORDER_CODE
from ame_condition_usages AmeConditionUsageEO,
fnd_lookups condition_type_lookup,
(select *
from fnd_lookups
where lookup_type = 'AME_APPROVER_ORDER'
and enabled_flag = 'Y') approver_order_lookup,
ame_conditions cond,
wf_roles wf,
(select *
from ame_attributes_vl
where sysdate between start_date and
nvl(end_date - (1 / 86400), sysdate)) atr,
(select *
from ame_item_classes_vl
where sysdate between start_date and
nvl(end_date - (1 / 86400), sysdate)) ic
where ((sysdate between AmeConditionUsageEO.start_date and
nvl(AmeConditionUsageEO.end_date - (1 / 86400),
sysdate)) or
(sysdate < AmeConditionUsageEO.start_date and
AmeConditionUsageEO.start_date <
nvl(AmeConditionUsageEO.end_date,
AmeConditionUsageEO.start_date + (1 / 86400))))
and sysdate between cond.start_date and
nvl(cond.end_date - (1 / 86400), sysdate)
and cond.condition_id =
AmeConditionUsageEO.condition_id
and cond.attribute_id = atr.attribute_id(+)
and nvl(atr.item_class_id, -99) = ic.item_class_id(+)
and condition_type_lookup.lookup_type =
'AME_CONDITION_TYPE'
and condition_type_lookup.enabled_flag = 'Y'
and condition_type_lookup.lookup_code =
upper(cond.condition_type)
and upper(cond.parameter_one) =
approver_order_lookup.lookup_code(+)
and cond.parameter_two = wf.name(+)) QRSLT,
AME_RULES_VL arv
WHERE (QRSLT.RULE_ID > 0 and
QRSLT.CONDITION_TYPE_CODE <> 'post')
and arv.RULE_ID = qrslt.rule_id
and QRSLT.description like '%EXPENSE_REPORT_TOTAL%less%5000%'
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章