我有这个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'
问题是最后一个过滤器确实忽略了所有其他过滤器,结果是获取了所有符合最后一个过滤器的数据。
答案 0 :(得分:5)
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'
答案 1 :(得分:2)
运算符优先级 当您在一个表达式中使用多个逻辑运算符时,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'
)
答案 2 :(得分:1)
使用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;
谢谢
答案 3 :(得分:1)
我想我会尝试通过合并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语句中使用*
;您应该只索取要使用的数据。)