MYSQL自联接如何工作?

Nic*_*ams 14 mysql

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

该查询旨在查找事件1之后1天的ID,开始日期和事件2的价格.

代码工作正常.但我不明白如何.

有人可以尽可能彻底地解释 - 查询的不同部分是什么以及它们的作用是什么?

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
Run Code Online (Sandbox Code Playgroud)

我真的很感谢你的帮助,无论出于什么原因,我都非常难以理解这一点.

djn*_*jna 17

我试图理解这一点的方法是在第一个标记为event1和一个event2的位置写出两个列表.然后列出每个列表中的几条记录(列表将完全相同),现在从下面描述中的WHERE开始.

我们从两个表中获取数据(确定相同的表使用了两次,但暂时尝试忽略它)

FROM mm_eventlist_dates event1
JOIN mm_eventlist_dates event2 
Run Code Online (Sandbox Code Playgroud)

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

  WHERE event1.id=$id
Run Code Online (Sandbox Code Playgroud)

所以我们希望来自event1的记录具有指定的记录ID.据推测,这只是一个记录.现在我们算出事件结束后的第二天.

 date_add(event1.enddate, INTERVAL 1 DAY)
Run Code Online (Sandbox Code Playgroud)

现在告诉我们event2的记录,他们需要在那个日期开始,

ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY)
Run Code Online (Sandbox Code Playgroud)

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

SELECT event2.id, event2.startdate, event2.price
Run Code Online (Sandbox Code Playgroud)

哦,只是我们想出的开始日期的字段.


Mac*_*ros 8

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

event1.id, event1.startdate, event1.price
Run Code Online (Sandbox Code Playgroud)

并加入表2(event2):

event2.id, event2.startdate, event2.price
Run Code Online (Sandbox Code Playgroud)

这给你留下了结果集:

event1.id, event1.startdate, event1.price, event2.id, event2.startdate, event2.price
Run Code Online (Sandbox Code Playgroud)

连接的条件指定为:

ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY)
Run Code Online (Sandbox Code Playgroud)

这是说'对于事件1中的每一行加入事件2中的行,事件在event1中的startdate后1天开始'

然后,因为您只对一个事件的数据感兴趣,所以where子句限制结果集.

WHERE event1.id=$id
Run Code Online (Sandbox Code Playgroud)

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

SELECT event2.id, event2.startdate, event2.price
Run Code Online (Sandbox Code Playgroud)


Sco*_*ott 6

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

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

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

考虑一个人员表,每个人都有一个唯一的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)  
Run Code Online (Sandbox Code Playgroud)

会产生1排

    childName   fatherName
    Greg       Joseph
Run Code Online (Sandbox Code Playgroud)


Vin*_*vic 5

连接根据特定条件组合两个表.标准遵循ON子句.

如果您将表连接到自身,它实际上与创建表的副本,重命名表并使用该副本执行连接相同.

例如

Table foo         Table bar
+---+---+---+     +---+---+---+
| a | b | c |     | a | d | e |
+---+---+---+     +---+---+---+
| 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)
Run Code Online (Sandbox Code Playgroud)

我们最终得到了


foo join bar on (foo.a = bar.a and foo.c > 4)
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
| 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
Run Code Online (Sandbox Code Playgroud)

该查询遵循相同的原则,但是使用表mm_eventlist_dates的两个实例,一个作为event1别名,另一个作为event2.我们可以将此视为具有两个表并执行连接,就像在真正的两个表方案中一样.

在这种情况下,连接标准是对于表event2,startdate匹配enddate加上表event1的一天.

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