有条件的WHERE子句,条件超过3个

时间:2019-04-19 14:51:34

标签: sql oracle plsql

我有一个带有条件WHERE子句的查询,其中我根据页面项从Table1中选择用户。

如果某个页面项的值为TYPE1或TYPE2,我从Table1中选择不在Table2中的用户,并满足第一个条件, 并且如果用户属于TYPE3,则在第二种情况下,我将从Table2中选择不在Table2中的用户。

现在我需要再添加两个类型TYPE4和TYPE5,但是困难在于,如果用户使用这两种类型中的任何一种, 在带有status='NEW'

的表2中应该不存在
      SELECT 1
      FROM   Table2 b
      WHERE  b.id = a.id            
         AND b.type_id = :P2_TEST_TYPE
         AND b.status = 'NEW'`

但应分别扮演“ PRIMARY”和“ SECONDARY”角色:

mypackage.get_role(a.id) = 'PRIMARY' AND mypackage.get_type_id(TO_NUMBER(:P2_TEST_TYPE))='TYPE4'

AND

mypackage.get_role(a.id) = 'SECONDARY' AND mypackage.get_type_id(TO_NUMBER(:P2_TEST_TYPE))='TYPE5'

下面处理TYPE1,TYPE2和TYPE3的查询。如何将TYPE4和TYPE5的条件纳入此查询:

SELECT a.ID, a.NAME
FROM Table1 a
WHERE NOT EXISTS
  (SELECT 1
      FROM   Table2 b
      WHERE  b.id = a.id            
         AND b.type_id = :P2_TEST_TYPE
         AND mypackage.get_category_id(b.parent_id) <> mypackage.get_category_id(:P2_PARENT_ID)
         AND b.status = 'NEW'
         AND mypackage.get_type_id(TO_NUMBER(:P2_TEST_TYPE)) IN ('TYPE1', 'TYPE2')
   UNION ALL
   SELECT 1
      FROM   Table2 b
      WHERE  b.id = a.id            
         AND b.type_id = :P2_TEST_TYPE
         AND b.status = 'NEW'
         AND mypackage.get_type_id(TO_NUMBER(:P2_TEST_TYPE)) = 'TYPE3'
  );            

2 个答案:

答案 0 :(得分:0)

由于两个子查询都非常相似,因此建议您将所有常见的AND条件提取到一个子查询中,并为每个替代条件添加一个额外的OR。然后,将每组条件按它们的公共子条件(与b.status有关的子条件)分组:

SELECT a.ID, a.NAME
FROM Table1 a
WHERE NOT EXISTS
(
    SELECT 1
    FROM   Table2 b
    WHERE  b.id = a.id            
        AND b.type_id = :P2_TEST_TYPE
        AND
        (
            (
                b.status = 'NEW' AND
                (
                    (
                        mypackage.get_type_id(TO_NUMBER(:P2_TEST_TYPE)) IN ('TYPE1', 'TYPE2')
                        AND
                        mypackage.get_category_id(b.parent_id) <> mypackage.get_category_id(:P2_PARENT_ID)
                    )
                    OR (mypackage.get_type_id(TO_NUMBER(:P2_TEST_TYPE)) = 'TYPE3')
                )
            )
            OR 
            (
                b.status <> 'NEW' AND
                (
                       (mypackage.get_role(a.id) = 'PRIMARY' AND mypackage.get_type_id(TO_NUMBER(:P2_TEST_TYPE))='TYPE4')
                    OR (mypackage.get_role(a.id) = 'SECONDARY' AND mypackage.get_type_id(TO_NUMBER(:P2_TEST_TYPE))='TYPE5')
                )
            )
        )
);

当然,它引发了太多的复杂性。您应该考虑改用客户端语言过程。

答案 1 :(得分:0)

决定在两个区域之间划分逻辑,然后使用show / hide显示适当的区域