Oracle SQL - 查询子表以查找匹配的父表

时间:2018-03-09 05:23:46

标签: sql oracle

Table vehicle_master
vehicle_id | vin
1          | 1234
2          | 5678
3          | 9123

Table vehicle_inventory

vehicle_id | key       | value
-----------|-----------|------
1          | Make      | Honda       
1          | Model     | Civic        
1          | Year      | 2004        
2          | Make      | Toyota
2          | Model     | Corolla
2          | Year      | 2005        
2          | color     | white   (every row is optnl: key/row may or may not exist in db)
3          | Make      | Honda       
3          | Model     | Civic        
3          | Year      | 2004     
3          | color     | blue

我正在尝试找到具有给定品牌,型号和颜色的车辆。可以在输入查​​询中指定颜色限制,但可能在DB中不可用。如果DB中的汽车没有指定颜色,即使在查询

中指定了颜色,也应匹配

到目前为止我的SQL:

select * from vehicle_master vm where 1=1
and exists(
    select 1 from vehicle_inventory vi
    where vi.vehicle_id=vm.vehicle_id
          and (vi.key=':make' and vi.value=':makeValue')
)
and exists(
    select 1 from vehicle_inventory vi
    where vi.vehicle_id=vm.vehicle_id
          and (vi.key=':model' and vi.value=':modelValue')
)
and exists(
    select 1 from vehicle_inventory vi
    where vi.vehicle_id=vm.vehicle_id
          and (vi.key=':color' and vi.value=':colorValue')
)

输入量:丰田,型号:卡罗拉,颜色:白色,我得到结果2 | 5678正如预期。

如果我输入Make:Honda,Model:Civic,Color:red,我得不到匹配或结果,因为本田的颜色键在DB中不存在。我希望在此实例中忽略颜色限制,因为没有数据库条目。我希望只有在颜色存在键和值的情况下才能在搜索中考虑颜色

如果存在具有密钥的行,如何使键/值对有条件地匹配,如果DB中不存在键/值行,则忽略该限制?

编辑:每个键都是可选的

4 个答案:

答案 0 :(得分:2)

我会在这里使用聚合。例如,要搜索白色的本田思域,我们可以尝试:

SELECT
    vm.vehicle_id,
    vm.vin
FROM vehicle_inventory vi
INNER JOIN vehicle_master vm
    ON vi.vehicle_id = vm.vehicle_id
GROUP BY vm.vehicle_id, vm.vin
HAVING
    SUM(CASE WHEN vi.key = 'Make'  AND vi.value = 'Honda' THEN 1 ELSE 0 END) > 0 AND
    SUM(CASE WHEN vi.key = 'Model' AND vi.value = 'Civic' THEN 1 ELSE 0 END) > 0 AND
    (SUM(CASE WHEN vi.key = 'color' AND vi.value = 'white' THEN 1 ELSE 0 END) > 0 OR
     SUM(CASE WHEN vi.key = 'color' THEN 1 ELSE 0 END) = 0);

HAVING条款的最后两个条款用简单的英语说,找到车辆颜色为的车辆,这些车辆根本没有颜色。

答案 1 :(得分:1)

尝试使用子查询和聚合,例如:

select b.vehicle_id, b.vin
from
    (select * from vehicle_master vm where
    exists(
        select 1 from vehicle_inventory vi
        where vi.vehicle_id=vm.vehicle_id
              and (vi.key='Make' and vi.value=':makeValue')
    )
    union all
    select * from vehicle_master vm where
    exists(
        select 1 from vehicle_inventory vi
        where vi.vehicle_id=vm.vehicle_id
              and (vi.key='Model' and vi.value=':modelValue')
    )
    union all
    select * from vehicle_master vm where
    exists(
        select 1 from vehicle_inventory vi
        where vi.vehicle_id=vm.vehicle_id
              and (vi.key='Color' and vi.value=':colorValue')
    )) b
group by b.vehicle_id, b.vin 
having count(*)=3;

你只需要3个变量,键是常量。

答案 2 :(得分:1)

通过不更改查询的结构,您可以将第三个子查询更改为约束NOT EXISTS。您可以检查它是否存在vehicle_inventory中的记录,其颜色与您要查找的记录不同:

and NOT exists(
    select 1 from vehicle_inventory vi
    where vi.vehicle_id=vm.vehicle_id
    and (vi.key=':color' and vi.value != ':colorValue')
)

答案 3 :(得分:1)

你可以说如果make的颜色存在则检查它,否则不要检查它。

SELECT  vm.*
  FROM  vehicle_master    vm
       ,vehicle_inventory mk
       ,vehicle_inventory mo
 WHERE  mk.vehicle_id = vm.vehicle_id
   AND  mk.key = 'Make'
   AND  mk.value = ':makeValue'
   AND  mo.vehicle_id = vm.vehicle_id
   AND  mo.key = 'Model'
   AND  mo.value = ':modelValue'
   AND  (EXISTS (SELECT 1
                   FROM vehicle_inventory co
                  WHERE vm.vehicle_id = co.vehicle_id
                    AND co.key = 'color'
                    AND co.value = ':colorValue') OR
     NOT EXISTS (SELECT 1
                   FROM vehicle_inventory co
                  WHERE vm.vehicle_id = co.vehicle_id
                    AND co.key = 'color') )