我想在两列中的一列上连接两个表。我不知道哪一个会匹配。当从列表表中找到匹配的行时,我想要feed_REIN中的所有记录和其他数据。我认为LEFT JOIN会起作用。
当我只有一个条件(即RETS.list_number = listings.CVMLS)时,它运行正常。一旦我在LEFT JOIN中添加额外的OR条件,就需要永远完成查询。
feed_RETS有大约125,000条记录,列表大约有12k条记录。
我做错了什么?
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%'
答案 0 :(得分:0)
试试这个:
SELECT
COUNT(*)
FROM feed_RETS AS RETS
LEFT JOIN listings on
RETS.list_number = listings.CVMLS
OR RETS.list_number = listings.REIN
WHERE public_status NOT LIKE '%Sold%' and statusID IN (1,2,3)
答案 1 :(得分:0)
查看解释计划以更好地理解带有OR子句的查询。对于此查询,唯一可能的连接算法可能是嵌套循环连接,这对于表来说效率非常低。您可以将查询重写为:
SELECT
COUNT(*)
FROM(
(SELCT * FROM feed_RETS AS RETS LEFT JOIN listings ON statusID IN (1,2,3) AND RETS.list_number = listings.CVMLS WHERE public_status NOT LIKE '%Sold%')
UNION
(SELCT * FROM feed_RETS AS RETS LEFT JOIN listings ON statusID IN (1,2,3) AND RETS.list_number = listings.REIN WHERE public_status NOT LIKE '%Sold%'))T
答案 2 :(得分:0)
如果您打算使用cvmls OR rein(exclusive或),并且应用程序确保其中任何一个都可以为true而不是两者,那么逻辑上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%'
;
由于两个原因(根据一般假设尽力诊断),您的查询可能仍然很慢:
OR
条件中的JOIN
会强制进行全表扫描,因为优化程序不知道要使用哪个索引或是否使用任何索引。%
开头的通配符'%Sold%
强制进行全表扫描,因为通过将列内容从左向右划分来构建正常类型的索引。将索引视为按字母顺序排列的名称列表:如果您在名称的开头匹配("名称以' Jo'"开头),您可以使用您的有序列表,以便快速找到匹配的名称;相反,如果您正在寻找名称中间的某些内容("名称中包含' 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%'
,那么查询可能会更快。