同一WHERE IN集的多个列

时间:2017-01-11 18:37:48

标签: sql oracle

我想我想找出所有特定人群中父母或子女的人。

我可以这样做:

SELECT *
FROM people P
WHERE
  P.parent_id IN ('111', 'abc', '42', '1a2b3c') OR
  P.child_id IN  ('111', 'abc', '42', '1a2b3c')

有什么方法可以避免两次写入列表(如果我要查找更多列,可以更多次)?

我正在寻找类似的东西:

(...) WHERE (P.parent_id OR P.child_id) IN ('111', 'abc', '42', '1a2b3c')

我使用的是Oracle,但是一个普通的SQL解决方案也会受到赞赏。

6 个答案:

答案 0 :(得分:2)

试试这个:

WITH search_ids (id) AS (
          SELECT '111'    FROM dual
UNION ALL SELECT 'abc'    FROM dual
UNION ALL SELECT '42'     FROM dual
UNION ALL SELECT '1a2b3c' FROM dual
) 
SELECT * FROM people P 
WHERE P.parent_id IN (SELECT id FROM search_ids)
  OR  P.child_id IN (SELECT id FROM search_ids)
;

FROM dual位是Oracle特定的。

快乐的玩耍

答案 1 :(得分:0)

您已使用OR,因此查询难以优化。因此,正则表达式是一个选项:

SELECT *
FROM people P
WHERE regexp_like('[' || P.parent_id || ']['  || p.child_id || ']') regexp_like('\[111|abc|42|1a2b3c\]') 

答案 2 :(得分:0)

一种方法是使用分层查询(然后它更通用 - 您可以按LEVEL使用不同的截止值):

select *
from   people
connect by level <= 2
       and parent_id = prior child_id
start with child_id in ( ..... )

最好还是拥有&#34;搜索ID&#34;在一个单独的表中,IN条件为in (select search_id from helper_table),如另一个答案中所示。

答案 3 :(得分:0)

CREATE TABLE #People(parent_id NVARCHAR(50),child_id NVARCHAR(50))
GO
INSERT INTO #People
    ( parent_id, child_id )
VALUES  ( N'111', -- parent_id - nvarchar(50)
      N'321331'  -- child_id - nvarchar(50)
      ),( N'111', -- parent_id - nvarchar(50)
      N'abc'  -- child_id - nvarchar(50)
      ),( N'42', -- parent_id - nvarchar(50)
      N'321331'  -- child_id - nvarchar(50)
      ),( N'111', -- parent_id - nvarchar(50)
      N'1a2b3c'  -- child_id - nvarchar(50)
      ),( N'11dsdfs1', -- parent_id - nvarchar(50)
      N'1a2sdfsdfsb3c'  -- child_id - nvarchar(50)
      )
;WITH CTE (Value) AS (
      SELECT '111'    
     UNION SELECT 'abc'   
     UNION SELECT '42'    
     UNION SELECT '1a2b3c' 
  ) 
SELECT *
FROM #People p
WHERE EXISTS(
    (SELECT p.parent_id 
    UNION 
    SELECT p.child_id
    )
    INTERSECT 
    SELECT value
    FROM CTE
)

答案 4 :(得分:0)

就性能和普遍性而言,对于这种情况,最好使用除const之外的其他方法。在Oracle中,有 SET 运算符可以帮助您。例如,对于您的情况,您的查询可能如下所示:

OR

或使用select * from people p where exists ( ( select p.parent_id from dual union all select p.child_id from dual ) intersect ( select '111' from dual union all select 'abc' from dual union all select '42' from dual union all select '1a2b3c' from dual ) ) 子句:

with

这种方法的好处:

  1. 在性能方面更好(正如已经提到的,优化器很难在查询中消化with people_list (value) as ( select '111' from dual union all select 'abc' from dual union all select '42' from dual union all select '1a2b3c' from dual ) select * from people p where exists ( ( select p.parent_id from dual union all select p.child_id from dual ) intersect ( select value from people_list ) ) ,尤其是当它们更复杂时。)
  2. 它更通用 - 实际上,如果它们在给定的值集中,您可以添加任意数量的列。
  3. 您可以使用架构中的任何现有表格,而不是从OR中进行选择。
  4. 这个子查询更容易集成到一个复杂的查询中(并且比我在第一点中已经提到的更有效)。

答案 5 :(得分:-1)

您可以使用以下内容对它们进行分组[简洁:从SQL multiple columns in IN clause获取的想法

WHERE (P.parent_id, P.child_id)  IN (('111','111'), ('abc','abc'),('42','42'), ('1a2b3c','1a2b3c'));