MySQL Join дважды на одной и той же таблице дает половину результата - PullRequest
1 голос
/ 20 апреля 2019

У меня есть 2 таблицы и я делаю запрос на соединение, дело в том, что в основной таблице у меня есть 2 столбца с идентификатором, который необходимо заменить полными именами из второй таблицы, поэтому я выполняю запрос к одной и той же таблице дважды.Дело в том, что он не имеет примерно половину записей, если я меняю положение соединений, то появляется вторая половина.данные в столбцах идентификатора 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)

1 Ответ

0 голосов
/ 20 апреля 2019

Ваш запрос выглядит довольно запутанным и может выполняться довольно медленно, создавая временные таблицы для использования в соединениях.

Также я не верю, что вам нужно 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. Обычно преимущества наличия индекса перевешивают над более медленными вставками.

...