MYSQL删除表本身的NOT IN子查询

时间:2016-12-15 15:18:08

标签: mysql database

我有以下查询,显示具有特定保证金级别的帐户列表:

SELECT
    crm_margincall.id,
    crm_margincall.CreationTime,
    ba.name AS crm_bankaccount_id,
    crm_margincall.name,
    crm_margincall.MarginCallLevel,
    crm_margincall.UseOfEquityForMargin,
    crm_margincall.MarginRequired,
    crm_margincall.NetEquityForMargin,
    crm_margincall.MarginDeficit,
    crm_margincall.balance,
    crm_margincall.deposited,
    crm_margincall.prefunded,
    crm_margincall.required
FROM 
    crm_margincall
LEFT JOIN
    crm_bankaccount ba ON crm_margincall.crm_bankaccount_id = ba.id
WHERE 
    crm_margincall.name = 'MarginCall' 
AND 
    crm_margincall.MarginCallLevel >= 100
AND 
    crm_margincall.crm_account_id NOT IN 
    (
    SELECT 
        x.crm_account_id 
    FROM 
        crm_margincall x 
    WHERE 
        x.crm_account_id = crm_margincall.crm_account_id 
    AND 
        x.name = 'LevelDrop' 
    AND 
        x.MarginCallLevel < 100 
    AND 
        x.id > crm_margincall.id
    )
ORDER BY 
    id
DESC

这个查询在~22.500记录的表上运行大于10秒,这是由定义NOT IN部分的子查询引起的(尝试NOT EXISTS,不是更快)。我怎样才能加入这个表来达到同样的效果呢?

2 个答案:

答案 0 :(得分:1)

  

此查询在~22.500条记录的表上运行时间> 10秒,   这是由定义NOT IN部分的子查询引起的(尝试NOT   EXISTS,不是更快)。我怎样才能将这张表连接到自己身上   达到同样的效果?

这可以通过多种方式完成,但扫描22500条记录需要10&#34;表示硬件问题或非常低效的JOIN。

后者最可能的原因是缺少索引或索引配置错误,要对此进行调查,您需要发出一个EXPLAIN:

EXPLAIN SELECT ...

完全在黑暗中拍摄,从所使用的列中判断,我试试

 CREATE INDEX test_index ON crm_margincall(name, crm_account_id, MarginCallLevel, id)

其他改进可能是可能的,但您需要在SQLfiddle中准备一些带有假数据的示例结构,以便真正进行调试。

答案 1 :(得分:0)

尝试这样的事情:

    SELECT
    crm_margincall.id,
    crm_margincall.CreationTime,
    ba.name AS crm_bankaccount_id,
    crm_margincall.name,
    crm_margincall.MarginCallLevel,
    crm_margincall.UseOfEquityForMargin,
    crm_margincall.MarginRequired,
    crm_margincall.NetEquityForMargin,
    crm_margincall.MarginDeficit,
    crm_margincall.balance,
    crm_margincall.deposited,
    crm_margincall.prefunded,
    crm_margincall.required
FROM 
    crm_margincall
LEFT JOIN
    crm_bankaccount ba ON crm_margincall.crm_bankaccount_id = ba.id
INNER JOIN 
(
    SELECT 
        x.crm_account_id 
    FROM 
        crm_margincall x 
    WHERE 
        x.name = 'LevelDrop' 
    AND 
        x.MarginCallLevel < 100 
    AND 
        x.id > crm_margincall.id
    ) tt ON crm_margincall.crm_account_id = tt.crm_account_id 
WHERE 
    crm_margincall.name = 'MarginCall' 
AND 
    crm_margincall.MarginCallLevel >= 100

ORDER BY 
    id
DESC