如何通过代码消除搜索中的人员

问题描述 投票:2回答:5

我有一个更复杂的情况,但我想我可以让这个例子更容易回答。假设我正在尝试查询那些在德克萨斯州并且只驾驶蓝色卡车的人。我正在使用Oracle数据库。

我有2个表(State table)和(Truck table)他们加入人员ID#

汽车表很大!这是最大的问题,因为我不希望查询挂起或运行很长时间。

州表

 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

如果有更好的方法来创建看起来像桌子的东西,我也想知道。

sql oracle
5个回答
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

这是小提琴

http://sqlfiddle.com/#!4/89bdc/14


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';

为了进行更多性能调优,我将首先查看执行计划和近似数据量。


0
投票

ADDED(事后):下面的解决方案只返回people标识符(本例中为222),而不是truck表中那些人的行(或行!)。如果需要完整行而不是聚合查询,则可以使用分析函数。易于修改,但首先回答我在原始问题的评论中提出的问题。结束编辑。

with
  state_table ( people, state ) as (
    select 111, 'TX' from dual union all  
    select 222, 'TX' from dual union all  
    select 333, 'CA' from dual
  ),
  truck_table ( people, dt, color ) as (
    select 111, 1995, 'Orange' from dual union all
    select 111, 1996, 'Blue'   from dual union all
    select 111, 1997, 'White'  from dual union all
    select 111, 2017, 'Blue'   from dual union all
    select 111, 2017, 'Gold'   from dual union all
    select 222, 2006, 'Blue'   from dual union all
    select 333, 2007, 'Blue'   from dual
  )
-- End of simulated inputs (for testing only, not part of the solution).
-- SQL query begins BELOW THIS LINE. Use your actual table and column names
select people
from   truck_table
where  people in ( select people
                   from   state_table
                   where  state = 'TX'
                 )
group by people
having count(case when color != 'Blue' or color is null then 1 end) = 0
;

    PEOPLE
----------
       222

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

-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表添加索引。

© www.soinside.com 2019 - 2024. All rights reserved.