我想我想找出所有特定人群中父母或子女的人。
我可以这样做:
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解决方案也会受到赞赏。
答案 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
这种方法的好处:
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
)
)
,尤其是当它们更复杂时。)OR
中进行选择。答案 5 :(得分:-1)
您可以使用以下内容对它们进行分组[简洁:从SQL multiple columns in IN clause获取的想法
WHERE (P.parent_id, P.child_id) IN (('111','111'), ('abc','abc'),('42','42'), ('1a2b3c','1a2b3c'));