我有一个更复杂的情况,但我想我可以让这个例子更容易回答。假设我正在尝试查询那些在德克萨斯州并且只驾驶蓝色卡车的人。我正在使用Oracle数据库。
我有2个表(State table
)和(Truck table
)
他们加入了人员ID#
Auto表非常庞大!这是最大的问题,因为我不希望查询挂起或运行很长时间。
州表
People State
------ -----
111 TX
222 TX
333 CA
卡车表
People Date Color
------ ---- ------
111 1995 Orange
111 1996 Blue
111 1997 White
111 2017 Blue
111 2017 Gold
222 2006 Blue
333 2007 Blue
我想要归还的只有222,因为他们没有任何其他颜色的卡车。
222 2006 Blue
如果有更好的方法来创建看起来像桌子的东西,我也想知道。
答案 0 :(得分:1)
如何使用。
select state.people, state, color, count(color)
from state, truck
where state.people = truck.people
and state.state = 'TX'
and color = 'Blue'
group by state.people, state, color
having count(color) = 1
这里是小提琴
答案 1 :(得分:0)
假设所有列都有NOT NULL约束:
select State.People
from State
join Truck on Truck.People = State.People
where State.State = 'TX'
and Truck.Color = 'Blue'
and not exists (
select null
from Truck t2
where t2.People = Truck.People
and t2.Color != 'Blue'
);
Truck (People, Color)
上的覆盖索引可能足以满足性能。
另一种考虑因素:
select State.People
from State
join Truck on Truck.People = State.People
where State.State = 'TX'
and Truck.Color = 'Blue'
minus
select Truck.People
from Truck
where Truck.People = Truck.People
and Truck.Color != 'Blue';
为了进行更多性能调优,我将首先查看执行计划和近似数据量。
答案 2 :(得分:0)
ADDED (事后):下面的解决方案只返回people
标识符(本例中为222),而不是{{1}的行(或行!)那些人的表。如果需要完整行而不是聚合查询,则可以使用分析函数。易于修改,但首先回答我在原始问题的评论中提出的问题。结束编辑。
truck
答案 3 :(得分:0)
如下所示尝试子查询:
select * from (select state.People, truck.Date, truck.Color,
count(truck.People) over (partition by state.People) Cnt from state
left join truck on state.People = truck.People and truck.Color = 'Blue'
where state.State = 'TX')
where cnt = 1
答案 4 :(得分:-1)
您可以首先使用JOIN查询表:
SELECT People, Date, Color
FROM Truck
INNER JOIN State ON Truck.People = State.People
WHERE State.State = 'TX'
AND Truck.Color = 'Blue'
如果查询性能不足,那么您可能希望在任一表上添加适当的索引。例如,您可能希望在Color属性上为Truck表添加索引。