我无法绕过连接

时间:2013-06-26 15:41:48

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

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

这是结构

ddCurrent
    -ID
    -Location
    -Status
    -Time

ddHistorical
    -CID (AI field to keep multiple records per site)
    -ID
    -Location
    -Status
    -Time

我现在的目标是进行一个简单的连接,从ddHistorical获取所有变量,从ddCurrent获取当前状态。

我知道他们可以加入ID,因为他们在ID表中都有相同的项目,我只是无法弄清楚哪种联接是合适的或为什么?

3 个答案:

答案 0 :(得分:0)

如果总是有一个当前字段,那么一个简单的INNER JOIN将会这样做

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

答案 1 :(得分:0)

INNER JOIN将省略ddHistorical中没有对应ID的所有ddCurrent行。

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

另请注意,LEFT JOIN只是特定类型的外部联接。不要打扰其他人 - 你所做的事情的90%或更多将是INNERLEFT

仅在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

如果您想要ddHistorical行,即使ddCurrent中的不是,也要包含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行恰好与{{1}}中的ID匹配,请注意两个查询都会返回相同的结果。

答案 2 :(得分:0)

我确信有人可能会提供详细说明的具体链接,但我会尝试用这种方式进行总结。在编写查询时,我尝试从我想要从哪个表中获取数据的位置列出表,并将其作为我在“FROM”子句中的第一个表。然后,根据关系(例如ID)对其他表执行“JOIN”条件。在你的例子中

FROM
   ddHistorical ddH
      INNER JOIN ddCurrent ddC
         on ddH.ID = ddC.ID

在这种情况下,INNER JOIN(与JOIN相同)ddHistorical表是左表(首先列出我的样式一致性和缩进),ddCurrent是正确的表。请注意我的ON标准将它们连接在一起也是alias.column = right alias table.column - 再次,这只是出于心理关联目的。

内部连接(或JOIN)表示记录必须在每一侧都有匹配,否则它将被丢弃。

LEFT JOIN意味着在LEFT表中给出所有记录(在本例中为ddHistorical),无论右侧表(ddCurrent)中是否匹配。在这个例子中不实用。

RIGHT JOIN是相反的...给我左侧表中的匹配记录的右侧表REGARDLESS的所有记录。大多数情况下,你会比RIGHT-JOIN更频繁地看到LEFT-JOIN。

现在,一个心理上得到左连接的样本。您在汽车经销商处工作,并拥有10辆汽车的主表。对于某个月,您想知道什么不卖。因此,从所有汽车的主表开始,查看销售表,了解DID的销售情况。如果没有此类销售活动,则右侧表将具有NULL值

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

所以,我的LEFT加入是基于匹配的车辆ID - 和 - 销售活动的月份是4(4月),因为我可能不关心1月至3月的销售 - 但也有资格年度,但这是一个简单的样本。

如果Car Sales表中没有记录,则所有列都将具有NULL值。我恰好关心汽车ID列,因为那是连接基础。这就是我在WHERE子句中包含它的原因。对于有销售的所有其他类型的汽车,它将具有价值。

这是一种常见的方法,你会在查询某个人寻找所有人而不管其他人的地方...有些人使用的地方是NOT EXIST(subselect),但是那些执行速度较慢,因为他们在每条记录上进行测试。加入的速度要快得多。

其他示例可能是您想要一个公司所有员工的列表,如果他们有一些认证/培训来展示它......您仍然想要所有员工,但是LEFT-JOINING到某个认证/培训表会暴露出来那些额外的领域。

select
      Emp.FullName,
      Cert.DateCertified
   FROM
      Employees Emp
         Left Join Certifications Cert
            on Emp.EmpID = Cert.EmpID

希望这些示例可以帮助您更好地了解查询之间的关系,现在实际上可以满足您的需求。

如果你想要的是所有“当前”项目的列表,并想看看他们的历史过去,我会使用当前的FIRST。这可能是你当前的事物表是50,但历史上你的表有420个项目。你不关心其他360项,只关注当前和那些历史。

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