在JOIN之前对两个表执行SELECT

时间:2014-07-08 15:42:17

标签: mysql select join inner-join

我没有太多使用JOIN的经验,也不是MySQL的专家。

在进行JOIN之前,我想要做的是两个表上的SELECT。为此,我试图使用括号,但语法不正确。

例如,在JOIN之前不进行SELECT:

DELETE tbA.* FROM tbA
INNER JOIN tbB
ON tbA.id_tbB = tbB.id_tbB
WHERE tbB.dateCol<'2014-01-01 00:00:00'

这样可行,但需要花费太多时间。我想做的事情没有成功,就像是:

DELETE tbA.* FROM (SELECT * FROM tbA WHERE tbA.id_tbB<=id_max)
INNER JOIN (SELECT * FROM tbB WHERE tbB.id_tbB<=id_max)
ON tbA.id_tbB = tbB.id_tbB
WHERE tbB.date<'2014-01-01 00:00:00'

我试图将它合成到基本问题......如果有人认为我应该提供更多信息(我想做什么,索引,外键......)我很乐意这样做,但基本上我只是想知道如何在INNER JOIN之前对两个表进行SELECT。

我想这样做是因为我的表有大量的记录(表A~1亿,表B~40000)。之前执行选择会将两个表上的记录数量减少到10%,并希望显着减少INNER JOIN,从而减少整体查询。

任何人都可以指出我的错误吗?谢谢!

3 个答案:

答案 0 :(得分:0)

怎么样

DELETE FROM tbA WHERE (select tbB.date from tbB where tbA.id_tbB = tbB.id_tbB) > '2014-01-01 00:00:00'

或替代

DELETE FROM tbA WHERE tbA.id_tdB IN (
     select tbB.id_tbB from tbB where tbB.date > '2014-01-01 00:00:00'
)

如果在tbA中id_tdB上有索引或外键,我会假设最后一个是最快的。

答案 1 :(得分:0)

你正在做的事情应该有用,你只是缺少一些重要的语法元素。您可以加入SELECT,这是一个名为派生表(virtual table)。您必须为派生表命名,以便引用它。您不能从派生表中删除它,因为它是虚拟表,它只存在于内存中。所以你需要在你的选择中放一个物理表。

尝试这样的事情:

DELETE tbA FROM tbA 
INNER JOIN (SELECT * FROM tbB WHERE tbB.id_tbB<=id_max AND tbB.date<'2014-01-01 00:00:00') AS tbB_filter
ON tbA.id_tbB = tbB_filter.id_tbB
WHERE tbA.id_tbB<=id_max

派生表可以使事情变得更快,因为它会事先过滤并将选择内容加载到内存中。由于它是派生表,因此它没有索引,因此如果派生表变得太大,实际上可能会减慢速度。从派生表中仅选择所需的字段以保持较低的内存占用。您总是可以在最后进行额外的连接,以获得所需的其他字段。

答案 2 :(得分:0)

嗯,我猜这个问题的实际答案(或至少其中一个):

如何在JOIN之前对两个表执行SELECT?

使用虚拟表......类似于:

SELECT tbA_filter.* FROM (SELECT tbA.* FROM tbA WHERE tbA.id_tbB<=id_max) AS tbA_filter 
INNER JOIN (SELECT * FROM tbB WHERE tbB.id_tbB<=id_max AND tbB.date<'2014-01-01 00:00:00') AS tbB_filter
ON tbA_filter.id_tbB = tbB_filter.id_tbB
WHERE tbA_filter.id_tbB<=id_max

但是,如果它是DELETE操作(如我的示例中所示),则不可能,因为删除虚拟表上的内容是没有用的(因为它是虚拟表,而不是真正的原始表)。

重要的是要考虑虚拟表没有索引...所以尝试使用没有索引的两个表来进行JOIN可能不明智因为它将需要永远(特别是在具有令人难以置信的巨大数量的表上行)。