Oracle SQL在哪里过滤多行

时间:2018-06-13 17:38:24

标签: sql oracle

我确信有一个简单的解决方案可以解决我想要做的事情,但我无法通过它来思考。

表A - 列 - ITEMNUM - ITEMNAME

                   1      Test1
                   2      Test2
                   3      Test3
                   4      Test4
                   5      Test5
                   6      Test6 

表B - 列 - ITEMNUM CHAR

                   1      A
                   1      B
                   2      A
                   2      C
                   3      A
                   3      D
                   4      A
                   4      E
                   5      A
                   5      F
                   6      A
                   6      F

我想做的是

select itemname 
from A, b
where a.itemnum = b.itemnum

然后我只想要char =' A'但是当B,C或D也有相同的itemnum时。 itemnum必须有一个char是' A'然后它可能是具有相同itemnum的其他东西,但它不能是B,C或D.并非所有itemnum都会有一个值为' A'的char。希望这是有道理的。

Test4,Test5和Test6应该是唯一返回的。

我必须将此代码放入另一个不允许我使用pl / sql的程序中。

建议?

4 个答案:

答案 0 :(得分:1)

在B上使用NOT EXISTS

进行自我联接
select itemname 
from A, b
where a.itemnum = b.itemnum
and not exists( select 1 from b2 where b2.itemnum = b.itemnum and b2.char in ('B', 'C', 'D'));

您可能也想开始使用ANSI连接语法:

select itemname 
from A
join b on a.itemnum = b.itemnum
where not exists( select 1 from b2 where b2.itemnum = b.itemnum and b2.char in ('B', 'C', 'D'));

答案 1 :(得分:1)

这样的事情应该有效

SELECT a.itemname
FROM a
WHERE EXISTS (
  SELECT 1
  FROM b
  WHERE b.itemnum = a.itemnum
  AND b.char = 'A'
)
AND NOT EXISTS (
  SELECT 1
  FROM b
  WHERE b.itemnum = a.itemnum
  AND b.char IN ('B', 'C', 'D')
)

编辑:不确定这是否是您想要的(请分享预期的结果结构和数据,例如您对表A和B所做的那样),但这可能是第二步:

SELECT a.itemname, b.char
FROM a
INNER JOIN b
ON b.itemnum = a.itemnum
WHERE EXISTS (
  SELECT 1
  FROM b b_char
  WHERE b_char.itemnum = a.itemnum
  AND b_char.char = 'A'
)
AND NOT EXISTS (
  SELECT 1
  FROM b b_char
  WHERE b_char.itemnum = a.itemnum
  AND b_char.char IN ('B', 'C', 'D')
)

编辑2:请查看此SQL Fiddle,了解其工作原理。

结果基本上是:

ITEMNAME | CHAR
---------+-----
Test4    | A
Test4    | E
Test5    | A
Test5    | F
Test6    | A
Test6    | F

答案 2 :(得分:1)

您可以使用listagg构建一个包含每个itemname所有字符的字符串。然后,您可以过滤A但没有BCD的行:

with    list as
        (
        select  ITEMNAME
        ,       listagg("CHAR") within group (order by "CHAR") chars
        from    TableA a
        join    TableB b
        on      a.ITEMNUM = b.ITEMNUM
        group by
                ITEMNAME
        )
select  *
from    list
where   chars like '%A%'
        and not regexp_like(chars, '[BCD]')

Example at SQL Fiddle.

答案 3 :(得分:0)

我的两分钱

select itemnum from (
   select a.itemnum, 
       max(case when b.char in ('B','C','D') then 'Y' else 'N' end) bad_check,
       max(case when b.char = 'A' then 'Y' else 'N' end) has_an_a
   from A, b
   where a.itemnum = b.itemnum
   group by a.itemnum
) where has_an_a='Y'
and bad_check='N';