我需要简化此查询,因为持有mysql的服务器无法在设置的时间限制内执行此操作。
SELECT `B`.*,
`C`.`name`,
DATE_ADD(`B`.`SAILING-DATE`, INTERVAL `B`.`NIGHTS` DAY) AS dataEnd
FROM `table1` AS B
INNER JOIN `table2` AS A
INNER JOIN `table3` AS C
WHERE `B`.`ID`=`A`.`ID`
AND `B`.`CAT`=`A`.`CAT`
AND `C`.`code`=`A`.`code`
AND (`B`.`NIGHTS`>=$aNumber AND `B`.`NIGHTS`<=$anotherNumber)
// where are other AND like this on `table1`
table1
和table2
约有25.000行。
我想把查询在table1
上执行第一个查询,而不是循环所有结果并为每个结果做一个查询,但我认为效率太低。
编辑:
这是解释:
EDIT2:
我无法添加索引原因字段ID
,CAT
和code
在每个表中都不是唯一的...每个表中都有更多行ID
CAT
和code
EDIT3:
我认为最好将所有分成子查询更简单..有人可以给我一个想法吗?谢谢!
答案 0 :(得分:3)
您可以尝试的一件事是:
SELECT `B`.*,
`C`.`name`,
DATE_ADD(`B`.`SAILING-DATE`, INTERVAL `B`.`NIGHTS` DAY) AS dataEnd
FROM (SELECT *
FROM `table1`
WHERE table1.NIGHTS >=$aNumber AND table1.NIGHTS <=$anotherNumber) AS B
INNER JOIN `table2` AS A ON `B`.`ID`=`A`.`ID` AND `B`.`CAT`=`A`.`CAT`
INNER JOIN `table3` AS C ON `A`.`code` = `C`.`code`
这将有效地预过滤table1中的行,只选择满足所需条件Nights
的行,从而减少其他表中连接所涉及的数量。
另请注意,您的JOIN条件应该在INNER JOIN之后使用ON - 在这个实例中您实际上不需要WHERE子句。
您应该调查的另一件事是查询计划 - 有关详细信息,请参阅EXPLAIN命令。
在这种情况下,您可以从ID,CAT和CODE列的索引中受益,但是,不是仅仅为所有内容添加索引,首先检查EXPLAIN的输出,以查看最佳节省的位置 - 添加索引插入数据时会产生费用。
修改强>
好的,因此子查询表现良好,但您担心无法预先过滤table1的情况。首先,让我们修改您的原始查询,然后尝试:
SELECT B.*,
C.name,
DATE_ADD(B.SAILING-DATE, INTERVAL B.NIGHTS DAY) AS dataEnd
FROM table1 AS B
INNER JOIN table2 AS A ON (B.ID=A.ID AND B.CAT=A.CAT)
INNER JOIN table3 AS C ON (A.code = C.code)
我想知道原始查询的奇怪格式(连接条件应该真正遵循您加入的表)是否会以某种方式混淆MySql。我也删除了不需要的后退,在我看来,使查询更难以阅读(和键入)。
如果效果不符合您的预期,请在table1和table2上发布SHOW INDEX的结果。可能是在table1中添加ID和CAT的组合以及table2中的ID和CAT组合索引(composite index)可能会提高您的效果。
答案 1 :(得分:1)
首先将连接条件放在连接中,以帮助数据库正确解释查询。这可能不会产生性能差异,但至少查询将更容易为人类解释。
查询中的别名名称不需要反引号。你现在没有它们,所以要保持一致,并将它们添加到任何地方,或者删除它们。
SELECT B.*,
C.`name`,
DATE_ADD(B.`SAILING-DATE`, INTERVAL B.`NIGHTS` DAY) AS dataEnd
FROM `table1` AS B
INNER JOIN `table2` AS A ON B.`ID`=A.`ID` AND B.`CAT`=A.`CAT`
INNER JOIN `table3` AS C ON C.`code`=A.`code`
WHERE (B.`NIGHTS`>=$aNumber AND B.`NIGHTS`<=$anotherNumber)
然后确保您拥有查询可以使用的索引,例如table2.NIGHTS
。您可以使用explain
command来确定查询使用的索引。