我有以下两个表
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
答案 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';