我有一个非常简单的(我认为这很简单,但我仍在努力!)问题。我有一张车的桌子。我有另一张车类表。我想加入一个到另一个去上车。
汽车桌很简单,有型号和品牌。类表还有一个模型,一个make和一个类的类。当我想将相同品牌的汽车组合在一起时,无论其型号如何,都会出现问题。
例如,我有两辆车:
id vehiclemake vehiclemodel
1 AUDI R8
2 AUDI Quattro
我有两节课:
id vehiclemake vehiclemodel classtype
1 AUDI R8 A
2 AUDI NULL B
AUDI R8将与A类相匹配。我希望所有其他AUDI不论其型号与B类都匹配。
我在这里有一些示例代码,所以你可以玩一玩!
create table #vehicle(id int, vehiclemake varchar(10), vehiclemodel varchar(10))
create table #vehicleclass(id int, vehiclemake varchar(10), vehiclemodel varchar(10), classtype varchar(1))
insert into #vehicle values(1, 'AUDI', 'R8')
insert into #vehicle values(2, 'AUDI', 'Quattro')
insert into #vehicleclass values(1, 'AUDI', 'R8', 'A')
insert into #vehicleclass values(2, 'AUDI', null, 'B')
select
*
from
#vehicle v
left join #vehicleclass vc on
(v.vehiclemake = vc.vehiclemake and v.vehiclemodel = vc.vehiclemodel)
drop table #vehicle
drop table #vehicleclass
上述声明未将Quattro记录加入B类记录
答案 0 :(得分:2)
在vehiclemodel
的联接上使用COALESCE,这样当vehicleclass
表上的模型为NULL时,车辆将匹配其自己的模型。
[编辑] :在阅读用户评论后,试试这个:
SELECT *
FROM #vehicle v
INNER JOIN #vehicleclass vc
ON v.vehiclemake = vc.vehiclemake
AND v.vehiclemodel = vc.vehiclemodel
UNION
SELECT *
FROM #vehicle v
INNER JOIN #vehicleclass vc
ON v.vehiclemake = vc.vehiclemake
AND vc.vehiclemodel IS NULL
WHERE NOT EXISTS(SELECT 1
FROM #vehicleclass vc2
where vc2.vehiclemake = v.vehiclemake
and vc2.vehiclemodel = v.vehiclemodel);
答案 1 :(得分:0)
可能这就是你想要的:
SELECT *
FROM #vehicle v
JOIN #vehicleclass vc ON v.vehiclemake = vc.vehiclemake
AND ( v.vehiclemodel = vc.vehiclemodel
OR ( vc.vehiclemodel IS NULL
AND v.vehiclemodel NOT IN (
SELECT vehiclemodel
FROM #vehicleclass
WHERE vehiclemodel IS NOT NULL )
)
)
输出:
id vehiclemake vehiclemodel id vehiclemake vehiclemodel classtype
1 AUDI R8 1 AUDI R8 A
2 AUDI Quattro 2 AUDI NULL B
答案 2 :(得分:0)
SELECT *
FROM #vehicle v
LEFT JOIN #vehicleclass vc
ON (v.vehiclemake = vc.vehiclemake
AND v.vehiclemodel = COALESCE(vc.vehiclemodel, v.vehiclemodel))
WHERE v.Id = vc.id
输出:
id vehiclemake vehiclemodel id vehiclemake vehiclemodel classtype
1 AUDI R8 1 AUDI R8 A
2 AUDI Quattro 2 AUDI NULL B
答案 3 :(得分:0)
我倾向于在这里使用UNION ALL
,因为你真的有两个要求。
尝试在单个查询中执行此操作是可能的,但通常会掩盖执行计划,因此索引不会以最佳方式使用。
SELECT *
FROM #Vehicle AS v
INNER JOIN #vehicleclass AS vc
ON vc.VehicleMake = v.VehicleMake
AND vc.VehicleModel = v.VehicleModel
UNION ALL
SELECT *
FROM #Vehicle AS v
INNER JOIN #vehicleclass AS vc
ON vc.VehicleMake = v.VehicleMake
AND vc.VehicleModel IS NULL
WHERE NOT EXISTS
( SELECT 1
FROM #vehicleclass AS vc2
WHERE vc2.VehicleMake = v.VehicleMake
AND vc2.VehicleModel = v.VehicleModel
);
要做到这一点,没有你可以使用的联盟:
SELECT *
FROM #Vehicle AS v
CROSS APPLY
( SELECT TOP 1 *
FROM #vehicleclass AS vc
WHERE vc.VehicleMake = v.VehicleMake
ORDER BY CASE WHEN vc.VehicleModel = v.VehicleModel THEN 0 ELSE 1 END
) AS vc;
这将取决于您在每个表上的索引,哪些表现更好。没有索引后者有一个更好的执行计划,因为它只需要两次扫描,但如果我为每个表添加索引:
CREATE NONCLUSTERED INDEX #IX_Vehicle__VehicleMake_VehicleClass ON #Vehicle (VehicleMake, VehicleModel) ;
CREATE NONCLUSTERED INDEX #IX_VehicleClass__VehicleMake_VehicleClass ON #Vehicle (VehicleMake, VehicleModel);
然后前者变得更有效率,因为它能够更好地利用指数。