在 7 个表之间加入

JOINS between 7 tables

我在之前的 post 中得到了很多帮助,这让我更好地理解了数据库模型。我已经阅读了有关 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 查询,基本上我想 link 表:

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 等之间的区别。但我一直在寻找丢失的 link。我认为仍然缺少一些逻辑。

我如何通过适当的 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'
  • INNER JOIN:只有 Return 两个
  • 中的数据
  • LEFT JOIN:总是 Return 数据在第一个 table,然后只有相关数据在第二个
  • RIGHT JOIN:始终 return 来自第二个 table 的数据,然后仅是相关数据形式 第一的。
  • FULL OUTER:始终 Return 来自所有 table 的所有数据并对齐 他们联系时。 (在 mySQL 中不可用)
  • CROSS JOIN:Return 来自第一个 table 的所有数据并将其与第二个 table 中的所有数据相关联,没有关系....所以如果第一个有 2 个记录table 第二个是 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' 然后会显示一条记录。 但是,如果没有记录,则 return.

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

如果没有与特定许可证类型相关联的人员或车辆,则不会 returned。 如果您也需要人员,那么我们必须将上述查询与以 在以 vehicle 开头的 person 和 union 中。

我已将 table 放在其他更符合逻辑的位置:

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 

这将导致所有人都拥有自己的车辆。 通过向最后一个左连接添加一些条件,您可以确定是否允许驾驶特定车辆。 如果您想要特定的人 and/or 特定的车辆,只需添加一个 WHERE 子句

更新

John has 1 drivers license, which has 2 licensetypes: B and AM. Both B and AM Licensetypes are connected to to the VehicleType: Scooter. Only Licensetype B, is connected to my VehicleType: Familywagon, when i change the vehicletype from Scooter to Familywagon, my value shows 0, that i'm not allowed to drive this vehicle

这与连接逻辑和数据模型有关。 因为驾照与人有关,而不是直接与车辆有关,所以使用左连接,车辆类型的条目数与许可证类型的车辆类型数一样多。

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

这可以通过创建一个虚拟 table 来避免,该虚拟 table 的子查询包含一个人可以驾驶的不同车辆类型。

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

请注意,如果您需要有关某个人的信息,那么在子查询中包含人员 table 可能是明智的,这样您可以缩小子查询的结果数量。