【问题标题】:How does a MYSQL Self-Join Work?MYSQL 自联接是如何工作的?
【发布时间】:2013-11-05 03:24:37
【问题描述】:

我最近问了一个关于自我加入的问题,我得到了很好的答案。

该查询旨在查找 Event2 的 ID、开始日期和价格,在 Event1 之后 1 天。

代码运行良好。 但我不明白怎么做。

有人可以尽可能详尽地解释一下查询的不同部分是什么以及它们的作用吗?

SELECT event2.id, event2.startdate, event2.price
FROM mm_eventlist_dates event1
JOIN mm_eventlist_dates event2 
ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY)
WHERE event1.id=$id

非常感谢您的帮助,无论出于何种原因,我都很难解决这个问题。

【问题讨论】:

  • 假设 event1 和 event2 是两个完全不相关的表,只是恰好包含完全相同的数据。

标签: mysql


【解决方案1】:

我试图理解这一点的方法是在一个标记为 event1 和一个 event2 的部分上写出两个列表。然后在每个列表中列出一些记录(列表将相同)现在从下面描述中的 WHERE 开始。

我们从两个表中获取数据(好的,同一个表使用了两次,但暂时忽略它)

FROM mm_eventlist_dates event1
JOIN mm_eventlist_dates event2 

从下往上阅读其余部分可能会有所帮助。

  WHERE event1.id=$id

所以我们想要来自 event1 的具有指定记录 ID 的记录。据推测,这正是一个记录。现在我们找出事件结束后的第二天。

 date_add(event1.enddate, INTERVAL 1 DAY)

现在告诉我们来自 event2 的记录,它们需要从那个日期开始,

ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY)

我们现在确定了两条记录,我们想要哪些字段?

SELECT event2.id, event2.startdate, event2.price

哦,只是我们计算出开始日期的字段。

【讨论】:

  • 感谢您的帮助。
【解决方案2】:

当您在查询中创建连接时,您实际上就是在这样做 - 将 2 个表连接在一起。这可以是 2 个不同的表或 2 个相同的表,没关系。指定连接时,如果表不同,则为表创建别名(在查询的其余部分中引用它的名称)很有用,如果它们相同,则必不可少。您的查询正在使用包含以下列的表 1 (event1):

event1.id, event1.startdate, event1.price

并加入表 2 (event2):

event2.id, event2.startdate, event2.price

这会给你留下结果集:

event1.id, event1.startdate, event1.price, event2.id, event2.startdate, event2.price

连接条件指定为:

ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY)

这就是说'对于 event1 中的每一行,加入 event2 中 startdate 为 event1 中 startdate 后 1 天的行'

那么由于您只对一个事件的数据感兴趣,因此 where 子句会限制结果集。

WHERE event1.id=$id

最后,由于您不需要 event1 中有关原始事件的信息,因此您的 select 语句只需从结果集中选择 event2 列:

SELECT event2.id, event2.startdate, event2.price

【讨论】:

  • 谢谢,您的回复很有帮助。
【解决方案3】:

自联接通过使用不同的选择标准两次引用同一个表来工作。将表的每个引用视为通过过滤原始表创建的不同“虚拟表”。通常,其中一个表使用 WHERE 子句“过滤”,第二个表在连接子句中“过滤”。这是最有效的方法,也可以在连接子句中“过滤”两者。

所以我们有两个基于同一个基础表中数据的虚拟表,它们连接在一起,就好像它们是两个完全独立的表一样。

关键在于您将数据存储在一个表中,根据上下文的含义略有不同。

考虑一张人表,每个人都有一个唯一的 id,还有一个父亲列

    id   name    fatherID
    1    Joseph  [null]
    2    Greg     1

    SELECT child.name as childName, father.name as fatherName
        FROM people as child
        INNER JOIN people as father on (child.fatherID = father.id)  

将产生 1 行

    childName   fatherName
    Greg       Joseph

【讨论】:

  • 这是我能要求的最简单的例子。非常感谢。
【解决方案4】:

联接根据特定条件组合两个表。条件是 ON 子句之后的内容。

如果你将一个表与其自身连接起来,它实际上与创建一个表的副本相同,重命名它并与该副本执行连接。

例如

表 foo 表栏 +---+---+---+ +---+---+---+ |一个 |乙 | c | |一个 | d |电子| +---+---+---+ +---+---+---+ | 1 | 2 | 3 | | 1 | 0 | 0 | +---+---+---+ +---+---+---+ | 1 | 3 | 4 | | 2 | 9 | 3 | +---+---+---+ +---+---+---+ | 1 | 3 | 5 | +---+---+---+ | 2 | 4 | 6 | +---+---+---+

如果我们这样做

select * from foo join bar on (foo.a = bar.a and foo.c > 4)

我们结束了

foo join bar on (foo.a = bar.a and foo.c > 4) +---+---+---+---+---+ |一个 |乙 | c | d |电子| +---+---+---+---+---+ | 1 | 3 | 5 | 0 | 0 | +---+---+---+---+---+ | 2 | 4 | 6 | 9 | 3 | +---+---+---+---+---+

现在,

SELECT event2.id, event2.startdate, event2.price 
FROM mm_eventlist_dates event1                     
JOIN mm_eventlist_dates event2 
ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY)
WHERE event1.id=$id

该查询遵循相同的原则,但具有表 mm_eventlist_dates 的两个实例,一个别名为 event1,另一个别名为 event2。我们可以把这想象成有两个表,并像在真正的两个表场景中一样执行连接。

本例中的联接条件是,对于表 event2,开始日期与结束日期加上表 event1 的一天相匹配。

where 子句限制了执行的连接,在这种情况下,它只对 event1 表中具有提供的 id 的行执行连接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 2012-02-23
    • 2020-12-05
    • 2011-04-03
    相关资源
    最近更新 更多