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中不存在键/值行,则忽略该限制?
编辑:每个键都是可选的
答案 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') )