【问题标题】:How to select all joined rows from 2 tables including null如何从 2 个表中选择所有连接行,包括 null
【发布时间】:2015-01-08 13:29:29
【问题描述】:

我目前有 2 个表,疫苗接种和疫苗接种类型,可以使用疫苗 ID 属性连接。

vaccination 基本上是疫苗类型和患者之间的多对多连接表。它有 3 个属性:vaccine_id、registration_no 和 date。 Vaccination_type 具有疫苗 ID、疫苗名称。

我想加入这两个表并获得这些条目:

vaccine_id vaccine_name registration_no date
1          influenza    1111            2015-01-15
2          hepatitis B  null            null
3          polio        1111            2015-01-15
4          hepatitis A  1112            2015-01-15

这意味着即使患者没有接种乙肝疫苗,我仍然希望该条目为空。但是我只想要一个特定的registration_no,在这种情况下是1111,换句话说我也希望甲型肝炎写为null,因为它不是由1111完成的。所以如果我处理1111,我的预期结果将是:

vaccine_id vaccine_name registration_no date
1          influenza    1111            2015-01-15
2          hepatitis B  null            null
3          polio        1111            2015-01-15
4          hepatitis A  null            null

我已尝试使用所有连接,但找不到完美运行的连接。任何建议将不胜感激,谢谢!

【问题讨论】:

  • 外连接可以完美运行。在可用的两种类型中,LEFT 版本比 RIGHT 更受欢迎。
  • 我觉得那是left join你累了吗?
  • 你所说的属性实际上在SQL世界中被称为列。它也是行,而不是条目。
  • 列是字段是属性。行是一个条目是一个元组。从逻辑、物理或应用程序 POV 中查看同一事物时的不同词汇表。来到这里的人可能会从略有不同的参考点查看数据。实际上,当时对数据的描述比物理更符合逻辑,因此属性更正确……如果您真的想在这个场所以这种方式开始分析“正确性”。
  • 如上所述,在问题中我看到两个实体:Patient 和 Vaccination_Type。它们彼此之间具有多对多的关系。从描述中,我假设属性 Registration_No 唯一标识患者。事实上,它被称为,而不是类似,哦,Patient_Id 表明还有另一个未披露的含义。不过,是否要求为每个患者列出每种疫苗,显示哪些已接种,哪些未接种?你想看看根本没有接种过疫苗的病人吗?如果是这样,您将需要查询中的所有三个表。

标签: mysql sql select join left-join


【解决方案1】:

如果您想要一次注册的信息,那么这应该是您的基表。然后您想获得该注册的所有疫苗接种类型。最后加入疫苗接种表以获取接种日期,如果该人从未得到它,则为 NULL:

SELECT
  registrations.registration_no,
  vaccination_type.vaccine_id,
  vaccination_type.name,
  vaccination.date
FROM
  registrations
  CROSS JOIN vaccination_type
  LEFT JOIN vaccination ON registrations.registration_no = vaccination.registration_no AND vaccination_type.vaccine_id = vaccination.vaccine_id
WHERE
  registrations.registration_no = 1111

小提琴:http://sqlfiddle.com/#!2/e8b2d/5

【讨论】:

  • 这行得通!我不知道我还应该包括注册表,我什至不知道交叉连接存在。非常感谢朋友!
【解决方案2】:

使用 LEFT JOIN 将两个表连接起来。

试试这个:

SELECT VT.vaccine_id, VT.vaccine_name, V.registration_no
FROM Vaccination_type VT 
LEFT JOIN vaccination V ON VT.vaccine_id = V.vaccine_id;

【讨论】:

  • 我已经编辑了我的问题,因为我发现我当前的 sql 查询有问题。
  • 实际上,左连接和常规内连接都将生成相同的结果集,除非至少有一种疫苗接种类型从未接种过,这可能不太可能。
【解决方案3】:

根据我现在理解的问题,您需要一份所有疫苗接种的列表,您需要查看所有患者(或特定患者)以了解患者接种和未接种的疫苗。是的,这是可能的,但它需要所有三个表。 Vaccination_Type 表包含所有疫苗接种的列表,Patients 表包含所有患者的列表。疫苗接种表包含患者已接种疫苗的列表。

第一步是为所有患者创建所有疫苗接种的笛卡尔积。这将为您提供所有疫苗接种的列表,并为每次疫苗接种提供所有患者的列表。

select   vt.vaccine_id, p.registration_no
from     Vaccination_Type vt
cross join Patients       p;

然后与现有的交叉表左连接。

select   vt.vaccine_id, p.registration_no, v.vaccination_date
from     Vaccination_Type vt
cross join Patients       p
left join Vaccinations    v
    on    v.vaccine_id = vt.vaccine_id
    and   v.registration_no = p.registration_no;

这将为您提供所有患者的所有疫苗接种。如果患者已接受疫苗接种,则随后是接种疫苗的日期。如果不是,则日期字段将为 NULL。

如果这是您定期需要的东西,例如报告,您可以创建上述查询的视图并从视图中选择。

如果您只想查看有关特定患者的此列表,则可以从视图中进行选择:

select   vaccine_id, registration_no, vaccination_date
from     All_Vaccinations
where    registration_no = 1111;

但是,如果某个特定患者的疫苗接种史主要是您想要的,您只需使用两个性能稍好一点的表即可获得:

select   vt.vaccine_id, v.vaccination_date
from     Vaccination_Type vt
left join Vaccinations    v
    on   v.vaccine_id = vt.vaccine_id
    and  v.registration_no = 1111;

请注意,registration_no 被排除在选择列表之外,因为我们不再使用患者表。我们可以使用 Vaccinations 表中的 registration_no 字段,但是如果患者错过了疫苗接种,不仅日期字段而且结果集的 registration_no 字段都将包含 NULL。没有理由公开 A) 您已经知道其值的字段,并且 B) 在某些行中将具有正确的值,而在其他行中将具有 NULL。这可能会导致一些混乱。当您一次查看多个患者的数据时,您必须使用三表连接,因为需要 registration_no 才能理解输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 2017-08-29
    • 1970-01-01
    • 2013-03-31
    • 1970-01-01
    • 2023-02-03
    相关资源
    最近更新 更多