MySQL在同一个表上加入两次会得到一半的结果

问题描述 投票:1回答:1

我有2个表并进行连接查询,事情是在主表中我有2列id需要用第二个表中的全名替换,这就是为什么我在同一个表上运行查询两次。事实是它没有大约一半的记录,如果我改变连接的位置,那么下半部分出现。标识符2列中的数据类似于:(271,272),(272,271)

    query = "SELECT * FROM (SELECT * from transactions {2} LIMIT {3}, {4}) as transactions " \
            "LEFT JOIN (SELECT account_number as dr, account_name as dr_n, acc_id, company_id, deleted FROM tb_accounts) as tb1 ON tb1.acc_id = transactions.dr_acc " \
            "LEFT JOIN (SELECT account_number as cr, account_name as cr_n, acc_id, company_id, deleted FROM tb_accounts) as tb2 ON tb2.acc_id = transactions.cr_acc " \
            "LEFT JOIN (SELECT document as doc_name, doc_id, company_id, deleted FROM documents ORDER BY documents.date DESC) as doc1 ON doc1.doc_id = transactions.document " \
            "and doc1.company_id = {0} and doc1.deleted = 0 " \
            "WHERE tb1.company_id = {0} and tb1.deleted = 0 and " \
            "tb2.company_id = {0} and tb2.deleted = 0 and " \
            "transactions.company_id = {0} and {1} transactions.deleted = 0".format(company_id, filter, sort, sn, en)
python mysql python-3.x
1个回答
0
投票

您的查询看起来非常复杂,并且可以通过生成要在连接中使用的临时表来执行得非常慢。

我也不相信你需要LEFT JOIN。相反它应该是JOININNER JOIN)。

您的问题的原因是LIMIT运算符发布在顶部。

我可以建议使用以下查询(看看我如何将它放在Python中 - 在数据库客户端中复制/粘贴和测试更方便):

query = """
    SELECT *
    FROM transactions as transactions
    JOIN tb_accounts as tb1
    ON tb1.acc_id = transactions.dr_acc AND tb1.deleted = 0 AND tb1.company_id = {0}
    JOIN tb_accounts as tb2
    ON tb2.acc_id = transactions.cr_acc AND tb2.deleted = 0 AND tb2.company_id = {0}
    JOIN documents as doc1
    ON doc1.doc_id = transactions.document
        AND doc1.company_id = {0}
        AND doc1.deleted = 0
    WHERE transactions.company_id = {0}
      AND transactions.deleted = 0
      {1}
    {2}
    LIMIT {3}, {4}
""".format(company_id, filter, sort, sn, en)

要优化上述查询的速度,以下索引将非常有用:

CREATE INDEX idx_del_comp_acc
ON tb_accounts (deleted, company_id, acc_id);

CREATE INDEX idx_del_comp_doc
ON documents (deleted, company_id, doc_id);

CREATE INDEX idx_del_comp_dr_acc
ON transactions (deleted, company_id, dr_acc);

CREATE INDEX idx_del_comp_cr_acc
ON transactions (deleted, company_id, cr_acc);

如上所述,在索引中包含列非常重要。

此外,运行查询时还有其他条件,以及您将运行的其他查询。在这种情况下,您可以添加更多索引或重新设计上述索引。

在查询前使用命令EXPLAIN来查看服务器将如何运行它以及将使用哪些索引。

但请记住,添加索引会增加INSERT和UPDATE请求的时间。通常,索引的好处超过了插入速度慢的时间。

© www.soinside.com 2019 - 2024. All rights reserved.