如果您打算无论是cvmls或收服(异或)和应用程序可以确保要么可能是真实的,但不是两者,那么在逻辑上的LEFT JOIN
是不必要的,查询总是会产生相同的行数。但是,如果两者都可以在同一行相匹配,那么请考虑是否要COUNT(*)所有可能的匹配,包括从加入的左侧重复]或COUNT(DISTINCT r.list_number)唯一不同的表] :
-- Query 1
SELECT COUNT(*)
FROM feed_RETS AS RETS LEFT JOIN listings
ON listings.statusID IN (1,2,3)
AND ( RETS.list_number = listings.CVMLS
OR RETS.list_number = listings.REIN
)
WHERE RETS.public_status NOT LIKE '%Sold%'
;
-- Query 2 - Is the count the same?
SELECT COUNT(*)
FROM feed_RETS
WHERE public_status NOT LIKE '%Sold%'
;
如果查询2返回一个不同的计数,那么请注意列表中有多行记录被多次计数。如果你不想这样做,那么你需要一个不同的计数 - 或者可能是下面的一个改进。
如果查询是为了限制由这个连接所有标准返回的行,那么你就需要一个INNER JOIN
(并且为了清楚起见可以在ON
标准以及移动到WHERE
条款):
SELECT COUNT(*)
FROM feed_RETS AS RETS INNER JOIN listings
ON ( RETS.list_number = listings.CVMLS
OR RETS.list_number = listings.REIN
)
WHERE listings.statusID IN (1,2,3)
AND RETS.public_status NOT LIKE '%Sold%'
;
您的查询仍可能有两个原因(尽我所能来诊断基于一般假设)慢:
- 在
JOIN
标准OR
强制执行全表扫描,因为优化器不知道使用哪个索引或是否使用任何索引。
- 通配符
%
在比赛串'%Sold%
开始强制执行全表扫描,因为指数的正常类型由从分栏的内容内置左到右。这样想按字母顺序排列的名单索引:如果你在一个名称的开头匹配(“与‘乔’开头的名称”),你可以用你的有序列表快速找到匹配的名称;相反,如果你正在寻找某个名字中间的东西(“名字中带有”nat“),那么你的索引对你来说就没用了。
该查询实际上可能会更快:
SELECT SUM(CASE
WHEN l_cvmls.cvmls IS NOT NULL OR l_rein.REIN IS NOT NULL
THEN 1
ELSE 0
END
) listing_count
FROM ( feed_RETS AS r LEFT JOIN listings l_cvmls
ON l_cvmls.statusID IN (1,2,3)
AND r.list_number = l_cvmls.CVMLS
) LEFT JOIN listings l_rein ON l_rein.statusID IN (1,2,3)
AND r.list_number = l_rein.REIN
WHERE r.public_status NOT LIKE '%Sold%'
;
如果你能避免'%Sold%'
和使用'Sold%'
相反,查询可能会更快依然。
没有解释计划,没有模式细节,没有统计数据,没有示例数据和输出:downvote。 – symcbean