SQL AND运算符无法正常工作

时间:2011-01-09 08:28:14

标签: sql

我有以下两个表

LandParcels表

Blockid ParcelNo storPri
======= ======== =======
52000105   3      State
52000105   4      Private
52000105   5      State

行动表

Blockid ParcelNo ActionTaken
======= ======== ===========
52000105   3      Received
52000105   3      Send to Computer
52000105   4      Received
52000105   5      Received

我想找到记录Received但不是Send to Computer

这是我的查询

select 
    l.blockid, l.parcelno 
from 
    landparcels l 
left join 
    actions ac on l.blockid = ac.blockid and l.parcelno = ac.parcelno 
where 
    ac.actiontaken = 'Received' 
    and ac.actiontaken <> 'Send to Computer'  
    and ac.blockid = 52000105 

结果是

Blockid ParcelNo 
======= ======== 
52000105   3
52000105   4
52000105   5

我想要ParcelNo 4和5

6 个答案:

答案 0 :(得分:1)

如果您的数据库支持tuple子句中的where,请尝试

select *
from landparcels
where (blockid, parcelno) in
(
    select blockid, parcelno
    from actions
    where actiontaken = 'Received'
)
and  (blockid, parcelno) not in
(
    select blockid, parcelno
    from actions
    where actiontaken = 'Send to Computer'
)

编辑以响应marc_s :否则,请尝试使用此版本,我认为这是ANSI,而不是

select *
from landparcels as p
where exists
(
    select 1
    from actions
    where actiontaken = 'Received'
    and blockid = p.blockid
    and parcelno = p.parcelno
)
and not exists
(
    select 1
    from actions
    where actiontaken = 'Send to Computer'
    and blockid = p.blockid
    and parcelno = p.parcelno
)

答案 1 :(得分:0)

select a.blockid
      ,a.parcelno
  from landparcels a
  join actions     b on(a.blockid = b.blockid and a.parcelno = b.parcelno)
 where b.action_taken in('Received', 'Send to Computer')
   and a.blockid = 52000105
 group 
    by a.blockid
      ,a.parcelno
having count(*) = 1
   and min(b.action_taken) = 'Received';

或者不那么花哨的东西,可以在寻找两个中的一个的特殊情况之外扩展:

select a.blockid
      ,a.parcelno
  from landparcels a
  join actions     b on(a.blockid = b.blockid and a.parcelno = b.parcelno)
 where b.blockid = 52000105
   and b.action_taken = 'Received'
   and not exists(
      select 'x'
        from actions x
       where x.action_taken = 'Send to Computer'
         and b.blockid  = x.blockid 
         and b.parcelno = x.parcelno
   );

我刚刚意识到,根据您的要求,您不需要加入landparcels,但我保留原样,以防您的实际需求需要该表中的数据。

<强>更新 添加了blockid过滤器

答案 2 :(得分:0)

您没有说明您正在使用的数据库系统 - 但在SQL Server上,您可以在此处使用此查询:

SELECT 
    lp.*
FROM 
    dbo.LandParcels lp
WHERE
    EXISTS(SELECT * FROM abo.ActionTaken a 
           WHERE a.blockid = lp.blockid 
             AND a.parcelno = lp.parcelno 
             AND a.ActionTaken = 'Received')
    AND NOT EXISTS(SELECT * FROM dbo.ActionTaken a 
                   WHERE a.blockid = lp.blockid 
                     AND a.parcelno = lp.parcelno 
                     AND a.ActionTaken = 'Send to Computer')

这导致此输出:

blockid parcelno    storePrio
52000105       4          Private
52000105       5          State

答案 3 :(得分:0)

SELECT Blockid, PacelNo FROM LandParcels
WHERE ( ParcelNo IN ( SELECT ParcelNo FROM Actions WHERE ActionTaken = 'Received')
AND ( ParcelNo NOT IN ( SELECT ParcelNo FROM Actions WHERE ActionTaken = 'Send to Computer')))

答案 4 :(得分:0)

请注意,在任何常用的数据库产品中,您都不太可能在AND运算符中找到一个简单的错误。这里的问题不是数据库引擎没有产生正确的结果,而是你不明白AND运算符的作用。

查看您的情况ac.actiontaken = 'Received' AND ac.actiontaken <> 'Send to Computer'。将要发生的是引擎将检查输出中的每个可能的行并确定它是否满足您指定的条件。所以,对于第一行是真的,动作是'收到'?是。动作是不是'发送到计算机'也是如此?当然。因此该行有资格。

事实上,任何带有'已接收'动作的行都符合条件,因为根据定义,行 < / em>'发送到计算机'。

有多种方法可以获得您想要的答案。这是我的首选:

SELECT DISTINCT a.blockid, a.parcelno FROM actions a 
WHERE a.blockid = 52000105 AND a.actiontaken = 'Received' AND NOT EXISTS
   (SELECT * FROM actions a2 WHERE a2.blockid = a.blockid AND 
                                   a2.parcelNo = a.parcelNo AND 
                                   a2.actiontaken = 'Send to Computer')

答案 5 :(得分:0)

@ Kirakun的'行构造函数'答案的另一个变体仍然是ISO / ANSI语法,但SQL Server确实支持这一点:

SELECT blockid, parcelno
  FROM landparcels
INTERSECT 
SELECT blockid, parcelno
  FROM actions
 WHERE actiontaken = 'Received'
EXCEPT 
SELECT blockid, parcelno
  FROM actions
 WHERE actiontaken = 'Send to Computer';