在数据库中,有一个名为category的表:
创建它是为了创建相邻列表模型树。这是当前表格内的内容:
在此示例中(您可以在底部找到源链接),以下sql代码用于获取表中的"叶子"元素,其中"叶子"元素是表中没有其他任何行的行行在"父级"列中使用其" category_id"。运行以下代码:
SELECT t1.name FROM
category AS t1 LEFT JOIN category as t2
ON t1.category_id = t2.parent
WHERE t2.category_id IS NULL;
先前的SQL代码的结果给出了以下结果:
例如,表中没有行在父列内部具有值为3,因此TUBE(category_id == 3)是"叶"元素。
问题:为什么该sql代码在逻辑上给出此结果?我很高兴这样做,因为它是我所需要的,但我无法将其背后的理由包扎起来。
示例的来源:http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
带有null检查的Outer joins是一种常见模式,用于查看表中是否存在记录,在这种情况下,检查category_id是否为parent。 与使用not exists或not in非常相似。
每当您看到此模式时:
认为:"在TableA中查找TableB中不存在的行。
您的查询的意思是"查找没有子级的类别"。 如果删除WHERE子句并向查询中添加更多列,则更容易理解:
SELECT t1.category_id,
t1.name,
t2.name AS ChildName
FROM category AS t1
LEFT JOIN category as t2 ON t1.category_id = t2.parent
这是您的查询中发生的事情:
从category表开始,将其别名为t1和t2。 从现在开始,我将参考别名。
对于t1中的每一行,在t2中查找将该t1行标识为其父级的所有记录
如果t1行没有子行,则t2.category_id将为null
我们只想过滤没有子项的t1行
好吧,我真的很接近理解! 第1行完善,第2行完善,第3行如果t1行没有子行,则Im混淆的地方t2.category_id将为null。 从一开始,t2.category_id列中的所有单元格都没有值吗?
想想"如果我找不到适合您的孩子,我会离开null代替您的孩子category_id"
那么这个推理正确吗?:FROM category AS t1 LEFT JOIN category as t2 ON t1.category_id = t2.parent首先列出所有t1s信息,然后仅添加MATCHING t2列的信息。 由于某些t1.category_id与任何t2.parent不匹配,因此对于t2.parent和t2.category_id它们都将具有NULL值。 从那里,代码说:WHERE t2.category_id IS NULL(我只想要那些不匹配的),并且只想要名称列SELECT t1.name? 这是否还意味着我可以将WHERE t2.category_id IS NULL;替换为WHERE t2.parent_id IS NULL;并获得相同的结果?
是的,在两种情况下您都是对的。 您的描述虽然比较技术性
如果您还没有一个,我亲爱的朋友应该从stackoverflow获得一个天才徽章
我认为如果重命名表别名会更容易看到发生了什么:
SELECT tparent.name
FROM category AS tparent
LEFT JOIN category as tchild
ON tparent.category_id = tchild.parent
WHERE tchild.category_id IS NULL;
现在,可能更容易看到您要查找的是没有子项的所有父类别名称的列表[tchild.category_id IS NULL]