Mysql 我能';Don’别把我的头缠在接头上

Mysql 我能';Don’别把我的头缠在接头上,mysql,join,left-join,inner-join,outer-join,Mysql,Join,Left Join,Inner Join,Outer Join,好吧,我有几张桌子。我当前的查询运行在一个“历史”表上。我想进行某种连接,以从当前表中获取最新状态。这些表共享一个类似的列,称为“ID” 这是结构图 ddCurrent -ID -Location -Status -Time ddHistorical -CID (AI field to keep multiple records per site) -ID -Location -Status -Time 我现在的目标是做

好吧,我有几张桌子。我当前的查询运行在一个“历史”表上。我想进行某种连接,以从当前表中获取最新状态。这些表共享一个类似的列,称为“ID”

这是结构图

ddCurrent
    -ID
    -Location
    -Status
    -Time

ddHistorical
    -CID (AI field to keep multiple records per site)
    -ID
    -Location
    -Status
    -Time
我现在的目标是做一个简单的连接,从ddHistorical获取所有变量,从ddCurrent获取当前状态


我知道它们可以在ID上联接,因为它们在ID表中都有相同的项,我只是不知道哪种联接是合适的,或者为什么?

如果总是有一个当前字段,那么简单的内部联接就可以了

SELECT a.CID, a.ID, a.Location, a.Status, a.Time, b.Status
FROM ddHistorical a
INNER JOIN ddCurrent b
ON a.ID = b.ID

内部联接
将忽略在
ddCurrent
中没有相应的
ID
的任何
ddHistorical

LEFT JOIN
将包括所有
ddHistorical
行,即使它们在
ddCurrent
中没有相应的
ID
,但
ddCurrent
值将为空(因为它们未知)

还要注意,
左连接
只是一种特定类型的外部连接。不要为别人操心——你将要做的90%或更多的事情都是
内部的
左侧的

要仅包括ID位于
ddCurrent
中的
ddHistorical
行,请执行以下操作:

SELECT h.CID, h.ID, h.Location, h.Status, c.Status, h.Time
FROM ddHistorical h
INNER JOIN ddCurrent c ON h.ID = c.ID
SELECT h.CID, h.ID, h.Location, h.Status, c.Status, h.Time
FROM ddHistorical h
LEFT JOIN ddCurrent c ON h.ID = c.ID
如果要包括
ddHistorical
行,即使ID不在
ddCurrent
中:

SELECT h.CID, h.ID, h.Location, h.Status, c.Status, h.Time
FROM ddHistorical h
INNER JOIN ddCurrent c ON h.ID = c.ID
SELECT h.CID, h.ID, h.Location, h.Status, c.Status, h.Time
FROM ddHistorical h
LEFT JOIN ddCurrent c ON h.ID = c.ID

如果所有
ddHistorical
行恰好与
ddCurrent
中的ID匹配,请注意,两个查询将返回相同的结果。

我相信有人可能会提供一个特定的链接来详细解释,但我将尝试以这种方式进行总结。在编写查询时,我尝试从要从中获取数据的表的位置列出表,并将其作为“from”子句中的第一个表。然后,根据关系(如ID)将条件“连接”到其他表。在你的例子中

FROM
   ddHistorical ddH
      INNER JOIN ddCurrent ddC
         on ddH.ID = ddC.ID
在本例中,ddHistorical表的内部联接(与联接相同)是左表(首先列出用于样式一致性和缩进),ddCurrent是右表。请注意,将它们连接在一起的条件也是left alias.column=right alias table.column——同样,这只是出于心理关联的目的

内部联接(或联接)意味着记录的每一侧必须有一个匹配项,否则它将被丢弃

左连接意味着不管右侧表(ddCurrent)中是否匹配,都会将左表(在本例中为ddhistoric)中的所有记录提供给我。在这个例子中不实用

右连接是相反的。。。给出右侧表中的所有记录,而不管左侧表中是否有匹配的记录。大多数情况下,您将比右连接更频繁地看到左连接

现在,一个示例,用于从心理上获得左连接。你在一家汽车经销店工作,有一个包含10辆售出汽车的主表。在给定的一个月内,你想知道什么东西卖不出去。因此,从所有汽车的主表开始,查看销售表,了解销售情况。如果没有此类销售活动,右侧表将具有空值

select
      M.CarID,
      M.CarModel
   from
      MasterCarsList M
         LEFT JOIN CarSales CS
            on M.CarID = CS.CarID
           AND month( CS.DateSold ) = 4
   where
      CS.CarID IS NULL
因此,我的左连接基于匹配的汽车ID——销售活动的月份是4月,因为我可能不关心1月至3月的销售情况——但也符合今年的条件,但这是一个简单的示例

如果汽车销售表中没有记录,则所有列的值都为空。我只是碰巧关心car ID列,因为这是连接的基础。这就是为什么我要把它包括在WHERE条款中。对于所有其他类型的汽车来说,这都是有价值的

这是一个常见的方法,你会看到在查询某人在哪里寻找所有的,而不管其他。。。有些使用where NOT EXIST(子选择),但那些执行速度较慢,因为它们对每个记录都进行测试。加入要快得多

其他的例子可能是你想要一份公司所有员工的名单,如果他们有一些认证/培训来显示。。。您仍然需要所有员工,但左键加入某个认证/培训表会根据需要暴露这些额外字段

select
      Emp.FullName,
      Cert.DateCertified
   FROM
      Employees Emp
         Left Join Certifications Cert
            on Emp.EmpID = Cert.EmpID
希望这些示例可以帮助您更好地理解查询之间的关系,现在可以为您的需求提供答案

如果您想要的是所有“当前”项目的列表,并且希望查看它们的历史记录,那么我会首先使用“当前”。如果您当前的物品表是50个,那么可能是这样,但从历史上看,您的表有420个物品。你不关心其他360个项目,只关心那些当前的项目和这些项目的历史

select
      ddC.WhateverColumns,
      ddH.WhateverHistoricalColumns
   from
      ddCurrent ddC
         JOIN ddHistorical ddH
            on ddC.ID = ddH.ID

您想为
ddhistoric
中的每个条目选择一行吗?当您说出ddhistoric中的所有值时,您需要一个左侧外部联接,ddhistoric位于左侧这是一个很棒的答案:)现在。。。外部联接做什么?联接有很好的视觉表示。请看前四个,但请注意,他们所称的
OUTER
也被称为
FULL OUTER
,并且
LEFT
RIGHT
也是
OUTER
的类型。在我上面的示例中,您可以使用
左外连接ddCurrent
,它与
左外连接ddCurrent
(不带
外部
)是一样的,-
外部
是可选的,因为
根据定义是
外部
。用文字解释可能会让人困惑,所以一定要看看链接中的图片。