我有这个MySQL查询:
SELECT * FROM forex_pair_signals AS SENALES
JOIN forex_pair_price AS PRECIO
ON SENALES.forex_pair_price_id = PRECIO.forex_pair_price_id
JOIN forex_pair AS PARES
ON PRECIO.forex_pair_id = PARES.forex_pair_id
WHERE
PRECIO.forex_pair_price_time >= '2019-02-01 00:00' AND
PRECIO.forex_pair_price_time <= '2019-02-07 01:00' AND
TIME (PRECIO.forex_pair_price_time) BETWEEN '06:00' AND '13:00' AND
PARES.forex_pair_id = 13 AND SENALES.forex_pair_signals_result = 1 AND
PRECIO.forex_pair_price_rsi >= '80.00'
OR PRECIO.forex_pair_price_rsi <= '20.00'
ORDER BY SENALES.forex_pair_signals_id DESC
此查询工作正常,但添加以下过滤器除外:
AND PRECIO.forex_pair_price_rsi >= '80.00' OR
PRECIO.forex_pair_price_rsi <= '20.00'
问题是最后一个过滤器确实忽略了所有其他过滤器,结果是获取了所有与最后一个过滤器相符的数据。
AND
在OR
之前进行求值,因为AND
具有更高的优先级。使用括号覆盖operator precendence:
WHERE
PRECIO.forex_pair_price_time >= '2019-02-01 00:00' AND
PRECIO.forex_pair_price_time <= '2019-02-07 01:00' AND
TIME (PRECIO.forex_pair_price_time) BETWEEN '06:00' AND '13:00' AND
PARES.forex_pair_id = 13 AND SENALES.forex_pair_signals_result = 1 AND
(
PRECIO.forex_pair_price_rsi >= '80.00'
OR
PRECIO.forex_pair_price_rsi <= '20.00'
)
或者您可以重写您的条件,所以它只是一个表达式:
PRECIO.forex_pair_price_rsi not between '20.01' and '79.99'
运算符优先级当您在一个表达式中使用多个逻辑运算符时,MySQL会在AND运算符之后计算OR运算符。这称为运算符优先级。1
SELECT true OR false AND false;
结果
true OR false AND false ----------------------- 1
SELECT (true OR false) AND false;
结果
(true OR false) AND false ------------------------- 0
因此您需要在这种情况下使用括号
WHERE
PRECIO.forex_pair_price_time >= '2019-02-01 00:00' AND
PRECIO.forex_pair_price_time <= '2019-02-07 01:00' AND
TIME (PRECIO.forex_pair_price_time) BETWEEN '06:00' AND '13:00' AND
PARES.forex_pair_id = 13 AND SENALES.forex_pair_signals_result = 1 AND
(
PRECIO.forex_pair_price_rsi >= '80.00' OR
PRECIO.forex_pair_price_rsi <= '20.00'
)
我想我将通过在WHERE子句中合并范围逻辑来尝试整理查询。
SELECT *
FROM forex_pair_signals AS senales
INNER JOIN forex_pair_price AS precio ON senales.forex_pair_price_id = precio.forex_pair_price_id
INNER JOIN forex_pair AS pares ON precio.forex_pair_id = pares.forex_pair_id
WHERE pares.forex_pair_id = 13
AND senales.forex_pair_signals_result = 1
AND precio.forex_pair_price_time BETWEEN '2019-02-01 00:00' AND '2019-02-07 01:00'
AND precio.forex_pair_price_rsi NOT BETWEEN '20.00' AND '80.00'
AND TIME(precio.forex_pair_price_time) BETWEEN '06:00' AND '13:00'
ORDER BY senales.forex_pair_signals_id DESC
您的最终WHERE子句条件可以重写为NOT BETWEEN,这完全可以避免该问题。
[我也冒昧地使您的表别名小写,并重新排列了WHERE子句条件,以首先将较简单/较轻的条件置于位置。
我认为此查询现在更加整洁。
(p.s。尽量避免在SELECT语句中使用*
;您应该只索取要使用的数据。)
您应该在使用OR函数的同时使用括号,因为它与括号中定义的一个或两个WHERE子句相对应。
SELECT * FROM forex_pair_signals AS SENALES
JOIN forex_pair_price AS PRECIO
ON SENALES.forex_pair_price_id = PRECIO.forex_pair_price_id
JOIN forex_pair AS PARES
ON PRECIO.forex_pair_id = PARES.forex_pair_id
WHERE
PRECIO.forex_pair_price_time >= '2019-02-01 00:00' AND
PRECIO.forex_pair_price_time <= '2019-02-07 01:00' AND
TIME (PRECIO.forex_pair_price_time) BETWEEN '06:00' AND '13:00' AND
PARES.forex_pair_id = 13 AND SENALES.forex_pair_signals_result = 1 AND
(PRECIO.forex_pair_price_rsi >= '80.00'
OR PRECIO.forex_pair_price_rsi <= '20.00')
ORDER BY SENALES.forex_pair_signals_id DESC;