在7个表之间加入

时间:2015-01-19 18:39:46

标签: mysql sql join left-join inner-join

我在上一篇文章中得到了很多帮助,这让我更好地理解了数据库模型。我已经阅读了关于JOINS的教程和解释,但我似乎无法弄明白,特此是我的数据库模型;

    ***Person***        ***DrivingLicense***  ***DrivingLicenseLicenseTypes***
ID                  ID                    ID
Name                ExpiryDate            DrivingLicense_ID
                    Person_ID             LicenseType_ID

***LicenseTypes***  ***LicenseTypeVehicleTypes*** ***VehicleTypes***    ***Vehicles***
ID                  ID                            ID                    ID
LicenseType         LicenseType_ID                VehicleType           Make
                    VehicleType_ID                                      Model
                                                                        VehicleType_ID
                                                                        Person_ID

Person: (1, 'Person1'), (2, 'Person2');
DrivingLicense: (1, '2015-01-01', 1), (2, '2015-10-01', 2);
VehicleTypes: (1, 'Car'), (2, 'Motorbike');
LicenseTypes: (1, 'Car'), (2, 'Motorbike');
Vehicles: (1, 'Ford', 'Focus', 1), (2, 'Chevrolet', 'Caprice', 1), (3, 'Ducati', 'Multistrada', 2);
LicenseTypeVehicleTypes: (1, 1, 1), (1, 1, 2), (1, 2, 2);
DrivingLicenseLicenseTypes: (1, 1, 1), (1, 2, 2);

现在我想运行一个SELECT查询,基本上我想链接表:

PersonID.ID -> DrivingLicense.ID
DLLT.DrivingLicense_ID -> DrivingLicense.ID
DLLT.LicenseType_ID -> LicenseTypes.ID
LTVT.LicenseType_ID -> LicenseTypes.ID
LTVT.VehicleType_ID -> VehicleTypes.ID
Vehicles.Type_ID -> Vehicletypes.ID

我试过了:

SELECT * FROM Person
INNER JOIN DrivingLicense.ID ON Person.ID = DrivingLicense.ID
INNER JOIN DrivingLicenseLicenseTypes ON DrivingLicense.ID = DrivingLicenseLicenseTypes.DrivingLicense_ID
INNER JOIN LicenseTypes ON DrivingLicenseLicenseTypes.LicenseType_ID = LicenseTypes.ID
INNER JOIN LicenseTypeVehicleTypes ON LicenseTypes.ID = LicenseTypeVehicleTypes
INNER JOIN VehicleTypes ON LicenseTypeVehicleTypes.VehicleType_ID = VehicleTypes.ID
WHERE x=y AND x=y

我认为我开始的方式错误并且让新手犯错,我尝试以OUTER JOIN开始,即使他们是空白也能得到结果。

我是从错误的脚开始,我是否需要转动步骤?

也许要澄清一些事情:

在我运行查询的这个页面之前,我有2个搜索字段,1个人是唯一的,1个是车辆唯一的。

基于这两个值,我正在检查它们是否匹配(检查该人是否确实是该值的所有者)。到目前为止一切都很好。

之后,我想根据我的许可证类型,车辆类型和我的许可证的到期日期来检查该人是否有效驾驶车辆。有驾驶摩托车许可证的人可能不会驾驶汽车。

因此,我已经在这里帮助调整了数据库设置,我已经阅读了INNER,OUTER,CROSS,LEFT JOINS等之间的差异。但我一直在寻找缺失的链接。我认为仍然缺少一些逻辑。

我如何通过apprioriate JOINS收集我需要的信息?我想避免使用我的情况:

SELECT table1, table2 FROM column1, column2

例如。

以下查询给出了双重结果:

SELECT * 
FROM RijbewijsTypes
LEFT JOIN RijbewijstypeVoertuigtype ON RijbewijstypeVoertuigtype.RijbewijstypeID = RijbewijsTypes.ID
LEFT JOIN RijbewijsRijbewijsType ON RijbewijsRijbewijsType.RijbewijstypeID
LEFT JOIN Rijbewijs ON Rijbewijs.ID = RijbewijsRijbewijsType.RijbewijsID
LEFT JOIN Persoon ON Persoon.ID = Rijbewijs.PersoonID
LEFT JOIN Voertuig ON Voertuig.PersoonID = Persoon.ID
LEFT JOIN Merk ON Merk.ID = Voertuig.Merk
LEFT JOIN Type ON Merk.Type = Type.ID
WHERE Persoon.BSNNummer =  '20230913'
AND Voertuig.Kenteken =  'NH-UN-78'

2 个答案:

答案 0 :(得分:1)

  • INNER JOIN:仅返回BOTH中的数据
  • LEFT JOIN:始终返回第一个表中的数据,然后仅返回第二个
  • 中的相关数据
  • RIGHT JOIN:始终从第二个表返回数据,然后只返回相关数据表 第一。
  • FULL OUTER:始终返回所有表格中的所有数据并对齐 当他们联系时他们。 (在mySQL中不可用)
  • CROSS JOIN:返回第一个表中的所有数据并将其与第二个表中的所有数据相关联,没有关系....所以如果第一个表中有2个记录而第二个表中有5个...总结果将是10个记录

所以试试吧......

SELECT * 
FROM LicenseTypes LT
LEFT JOIN LicenseTypeVehicleTypes LTVH
 on LTVH.LicenseType_ID = LT.ID
LEFT JOIN DrivingLIcense DL
 on DL.ID = DLLT.DrivingLicense_ID
LEFT JOIN Person P
 on P.ID = DL.Person_ID
LEFT JOIN LicenseTypeVehicleTypes LTVT
 on LTVT.LicenseType_ID = LT.ID
LEFT JOIN VehicleTypes VT
 on VT.ID = LTVT.VehicleType_ID
LEFT JOIN Vehicles V
 on V.ID = VT.ID
WHere P.Name = 'Person1' and V.ID = 'VIN'

如果Person1具有许可证类型'X'且'VIN'具有许可证类型'X' 然后将显示一条记录。 但是,如果没有记录将返回。

如果没有提供where子句,则所有许可证类型将与人员和车辆一起返回 它使用这些许可证类型。

如果没有与特定许可类型相关联的人或车辆将被退回。 如果你也需要这些人,那么我们必须将上述查询与一个开始的查询结合起来 以车辆开头的人和工会。

答案 1 :(得分:0)

我已将这些表放在另一个逻辑中:

SELECT DISTINCT
    p.name,
    v.VehicleType,
    v.make,
    v.model,
    CASE
       WHEN ltvt.VehicleType_ID =  v.VehicleType_ID THEN 1
       ELSE 0
    END allowed
FROM
    Person p
JOIN
    Vehicles v
    ON p.ID = v.person_id
LEFT JOIN
    DrivingLicense dl
    ON p.ID = dl.Person_ID
LEFT JOIN
    DrivingLicenseLicenceType dlt
    ON dl.ID = dlt.DrivingLicense_ID
LEFT JOIN
    LicenseTypes lt
    ON dlt.LicenseType_ID = lt.ID
LEFT JOIN
    LicenseTypeVehicleTypes ltvt
    ON dlt.LicenseType_ID = ltvt.LicenseType_ID
    AND ltvt.VehicleType_ID = v.VehicleType_ID
    AND dl.ExpiryDate >= CURRENT_DATE 

这将导致所有人拥有他们拥有的车辆。 通过向最后左侧连接添加一些条件,您可以确定是否允许驾驶某辆车。 如果您想要特定人员和/或特定车辆,只需添加WHERE子句

<强>更新

  

John有1个驾驶执照,它有2种许可类型:B和AM。 B和AM许可类型都连接到VehicleType:Scooter。只有Licensetype B连接到我的VehicleType:Familywagon,当我将车型从Scooter更改为Familywagon时,我的值显示为0,我不允许驾驶此车辆

这与连接逻辑和数据模型有关。 由于驾驶执照与人有关而不是直接与车辆有关,因此左侧车辆的车型将具有与许可证类型所具有的车型数量一样多的条目。

在你的情况下,John的Familywagon将会在结果中出现两次,一次是用于许可类型的踏板车部分(他不允许驾驶汽车),一次用于Familywagon部分(他被允许驾驶汽车。)

这可以通过创建一个带有子查询的虚拟表来避免,该子查询具有允许某人驾驶的不同车型。

SELECT
    p.name,
    v.VehicleType_ID,
    v.make,
    v.model,
    CASE
        WHEN dls.VehicleType_ID =  v.VehicleType_ID THEN 1
        ELSE 0
    END allowed
FROM
    Person p
JOIN
    Vehicles v
    ON p.ID = v.Person_ID
LEFT JOIN
    (SELECT DISTINCT
        dl.Person_ID,
        ltvt.VehicleType_ID
    FROM
        DrivingLicense dl       
    JOIN
        DrivingLicenseLicenseTypes dlt
        ON dl.ID = dlt.DrivingLicense_ID
    JOIN
        LicenseTypes lt
        ON dlt.LicenseType_ID = lt.ID
    JOIN
        LicenseTypeVehicleTypes ltvt
        ON dlt.LicenseType_ID = ltvt.LicenseType_ID
    WHERE
        dl.ExpiryDate >= CURRENT_DATE
    ) dls
    ON p.ID = dls.Person_ID
        AND dls.VehicleType_ID =  v.VehicleType_ID

请注意,如果您需要有关某个人的信息,则可以明智地将子表包含在子查询中,这样您就可以缩小子查询的结果数量。