我有2个表并进行联接查询,但事实是,在主表中我有2列ID需要用第二个表中的全名替换的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)
答案 0 :(得分:0)
您的查询看起来很复杂,并且可以通过生成要在联接中使用的临时表来相当慢地执行。
我也不认为您在那里需要LEFT JOIN
。相反,它应该是JOIN
(INNER 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请求的时间。通常,索引比插入慢一点的好处多。