我没有太多使用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,从而减少整体查询。
任何人都可以指出我的错误吗?谢谢!
答案 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可能不明智因为它将需要永远(特别是在具有令人难以置信的巨大数量的表上行)。