Sql 捕获联接表达式中的所有记录

Sql 捕获联接表达式中的所有记录,sql,tsql,join,sql-server-2008-r2,left-join,Sql,Tsql,Join,Sql Server 2008 R2,Left Join,我有一个非常简单的问题(我认为很简单,但我仍在努力!)。我有一桌汽车。我有另一张汽车分类表。我想一个接一个地参加,以获得这辆车的等级 cars表很简单,有模型和品牌。类表还具有一个模型、一个make和一个类类型。当我想将同一品牌的汽车组合在一起,而不考虑它们的型号时,问题就出现了 例如,我有两辆车: id vehiclemake vehiclemodel 1 AUDI R8 2 AUDI Quattro 我有两门课: id vehicle

我有一个非常简单的问题(我认为很简单,但我仍在努力!)。我有一桌汽车。我有另一张汽车分类表。我想一个接一个地参加,以获得这辆车的等级

cars表很简单,有模型和品牌。类表还具有一个模型、一个make和一个类类型。当我想将同一品牌的汽车组合在一起,而不考虑它们的型号时,问题就出现了

例如,我有两辆车:

id  vehiclemake vehiclemodel
1   AUDI            R8
2   AUDI            Quattro
我有两门课:

id  vehiclemake vehiclemodel    classtype
1   AUDI            R8          A
2   AUDI            NULL        B
奥迪R8将匹配A类车型。我希望所有其他奥迪车型,无论其车型如何,都匹配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类记录

车辆模型
的连接上使用a,这样当
车辆类
表上的模型为空时,车辆将与其自己的模型匹配

[编辑]:阅读用户评论后,尝试以下操作:

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

也许这就是你想要的:

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
输出:

id  vehiclemake vehiclemodel    id  vehiclemake vehiclemodel    classtype
1       AUDI        R8          1       AUDI        R8              A
2       AUDI      Quattro       2       AUDI        NULL            B

我倾向于在这里使用
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);
    

    然后前者变得更有效,因为它能够更好地利用索引搜索。

    在这种情况下,您希望得到什么输出?SQLFiddle链接:在本例中,结果应为:1奥迪R8 1奥迪R8 A 2奥迪Quattro 2奥迪空BIs在车型为空的表vehicleclass中,每辆车最多有1条记录?是,每个车型/车辆只生成一条记录,其中model/null为全部,但它为R8带回了两条记录,其中它与车型匹配,且车型为null。对于R8记录,它应该只在一次Hello!我想我们可能会赢!这些
    Id
    值在表之间匹配只是巧合。该列不是要匹配的有效列。
    CREATE NONCLUSTERED INDEX #IX_Vehicle__VehicleMake_VehicleClass ON #Vehicle (VehicleMake, VehicleModel) ;
    CREATE NONCLUSTERED INDEX #IX_VehicleClass__VehicleMake_VehicleClass ON #Vehicle (VehicleMake, VehicleModel);