MySQL соединение дважды в одной и той же таблице дает половину результата

#python #mysql #python-3.x

#python #mysql #python-3.x

Вопрос:

У меня есть 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. Не на 100% ясно, что означают ваши параметры. Если бы вы могли предоставить их примерные значения, я мог бы немного скорректировать свой ответ. Также не могли бы вы предоставить примерные данные и какие различия у вас есть при изменении позиций соединений. Пожалуйста, отредактируйте свой вопрос вместо публикации дополнительной информации в комментариях

Ответ №1:

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

Также я не верю, что вам это нужно LEFT JOIN . Вместо этого должно быть JOIN ( INNER JOIN ) .

И причиной вашей проблемы является оператор ОГРАНИЧЕНИЯ, размещенный сверху.

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

Однако имейте в виду, что добавление индекса увеличивает время запросов на вставку и ОБНОВЛЕНИЕ. Обычно преимущества наличия индекса в разы перевешивают более медленные вставки.

Комментарии:

1. Просто протестировал, и это сработало. Спасибо. единственная проблема, с которой я столкнулся, заключается в том, что у меня 1 миллион баз данных в транзакциях, и для перечисления 1000 записей требуется 2 минуты.

2. @SandroShubladze, я добавил индексы к своему ответу.

3. Спасибо, я буду использовать это.

4. Я попробовал, и это было идеально и дало великолепную производительность. Большое вам спасибо