在SQL中加入和子查询

时间:2015-02-03 07:09:13

标签: sql oracle

假设一个具有属性的表事务:mid,symbol

假设数据

mid symbol
1   b
2   b
3   c
4   b
5   e
2   e
1   e

这个问题要求找到所有符号为mid = 2

的mid

4 个答案:

答案 0 :(得分:1)

试试这个。我不确定ORACLE,但我认为它应该有用。

DECLARE @t TABLE ( mid INT, symbol CHAR(1) )
INSERT  INTO @t
VALUES  ( 1, 'b' ),
        ( 2, 'b' ),
        ( 3, 'c' ),
        ( 4, 'b' ),
        ( 5, 'e' ),
        ( 2, 'e' ),
        ( 1, 'e' )

SELECT DISTINCT
        t2.mid
FROM    @t t1
        JOIN @t t2 ON t2.symbol = t1.symbol
WHERE   t1.mid = 2
GROUP BY t2.mid
HAVING  COUNT(DISTINCT ( t2.symbol )) = ( SELECT    COUNT(DISTINCT symbol)
                                          FROM      @t
                                          WHERE     mid = 2
                                        )
ORDER BY t2.mid

输出:

mid
1
2

如果您不希望输出mid = 2,只需更改即可 WHERE t1.mid = 2WHERE t1.mid = 2 AND t2.mid <> 2

但是我想提一下,这个查询也会返回这样的mids,其符号集由一组mid = 2组成,可能是其他一些值。

答案 1 :(得分:0)

如果数据中有更多符号,请尝试使用NB,假设您希望所有需要更复杂方法的共享。需要适应Oracle

select 1 as mid,   'b' as Symbol into #Data
union all
select 2,   'b'
union all
select 3,   'c'
union all
select 4,   'b'
union all
select 5,   'e'
union all
select 2 ,  'e'
union all
select 1,   'e'

select D.Mid
From
(select B.Mid, B.Symbol
From #Data B
inner join (select Symbol
from #Data
where mid = 2) A on B.Symbol = A.Symbol) C
inner join 
(select B.Mid, B.Symbol
From #Data B
inner join (select Symbol
from #Data
where mid = 2) A on B.Symbol = A.Symbol) D On D.Mid = C.Mid and D.Symbol <> C.Symbol
inner join
(select B.Mid, COUNT(Distinct B.Symbol) as SC
From #Data B
inner join (select Symbol
from #Data
where mid = 2) A on B.Symbol = A.Symbol
Group By B.Mid) E ON C.Mid = E.Mid
inner join
(select B.Mid, COUNT(Distinct B.Symbol) as SC
From #Data B
inner join (select Symbol
from #Data
where mid = 2) A on B.Symbol = A.Symbol
Group By B.Mid) F ON D.Mid = F.Mid
Where D.Mid <> 2 and E.SC = F.SC
Group by D.Mid

答案 2 :(得分:0)

最里面的子查询返回主查询mid的所有符号。不存在确保没有丢失mid = 2符号。

select * from table t1
where not exists (select 1 from table
                  where mid = 2
                  and symbol not in (select symbol from table t2
                                     where t1.mid = t2.mid
                                       and symbol is not null))                    

答案 3 :(得分:0)

CREATE TABLE TAB1 AS
SELECT 1 MID,'b' SYMBOL FROM DUAL UNION ALL
SELECT 2 MID,'b' SYMBOL FROM DUAL UNION ALL
SELECT 3 MID,'c' SYMBOL FROM DUAL UNION ALL
SELECT 4 MID,'b' SYMBOL FROM DUAL UNION ALL
SELECT 5 MID,'e' SYMBOL FROM DUAL UNION ALL
SELECT 2 MID,'e' SYMBOL FROM DUAL UNION ALL
SELECT 1 MID,'e' SYMBOL FROM DUAL; 

首先得到mid = 2的所有不同符号。为mid = 2添加不同符号的计数(使用交叉连接)。将这些符号连接到非2-mids的所有符号。按中间和中间2个符号计数分组,并且仅选择至少匹配中间2个符号计数符号的中间符号(或恰好是2个符号计数符号中间,请参阅尾随注释)

SELECT MID
FROM
    (SELECT DISTINCT SYMBOL FROM TAB1 WHERE MID=2)
CROSS JOIN
    (SELECT COUNT(DISTINCT SYMBOL) C FROM TAB1 WHERE MID=2)
NATURAL JOIN
    (SELECT DISTINCT MID, SYMBOL FROM TAB1 WHERE MID <> 2)
GROUP BY MID, C 
HAVING COUNT(DISTINCT SYMBOL) >= C;

...将HAVING COUNT(DISTINCT SYMBOL) >= C更改为HAVING COUNT(DISTINCT SYMBOL) = C,如果您希望mids与mid = 2具有完全相同的符号,而不是其他符号。

编辑:如果(MID,SYMBOL)是一个唯一键,那么你可以放弃所有&#34; DISTINCT&#34;解决方案中的关键字。如果(MID,SYMBOL)不是唯一的,你需要返回匹配mid = 2的每个符号的所有出现的MID(所以,如果(2,&#39; b&#39;)发生两次,mid = 1只有在(1,&#39; b&#39;)出现至少两次时才有资格),那么SQL将是:

SELECT MID
FROM
    (SELECT SYMBOL, COUNT(*) SYMBOL_COUNT1 FROM TAB1 WHERE MID=2
     GROUP BY SYMBOL)
CROSS JOIN
    (SELECT COUNT(DISTINCT SYMBOL) C FROM TAB1 WHERE MID=2)
NATURAL JOIN
    (SELECT MID, SYMBOL, COUNT(*) SYMBOL_COUNT2 
     FROM TAB1 WHERE MID <> 2
     GROUP BY MID, SYMBOL)
WHERE SYMBOL_COUNT2 >= SYMBOL_COUNT1
GROUP BY MID, C 
HAVING COUNT(DISTINCT SYMBOL) >= C;

...在这种情况下,将SYMBOL_COUNT2 >= SYMBOL_COUNT1更改为SYMBOL_COUNT2 = SYMBOL_COUNT1会将结果限制为具有完全相同的每个符号出现次数的中间数;因此,如果(2,&#39; b&#39;)发生两次并且(1,&#39; b&#39;)发生了3次或更多次,则将排除1。