У меня есть таблица customer, в которой хранятся customer_id, адрес электронной почты и ссылка. Существует дополнительная таблица customer_data, в которой хранится историческая запись изменений, внесенных в клиента, то есть при внесении изменений вставляется новая строка.
Чтобы отобразить информацию о клиенте в таблице, необходимо объединить две таблицы, однако только самая последняя строка из customer_data должна быть присоединена к таблице клиентов.
Это немного усложняется тем, что запрос разбивается на страницы, поэтому имеет ограничение и смещение.
Как я могу это сделать с MySQL? Я думаю, что хочу где-нибудь поставить ОТЛИЧИТЕЛЬНЫЙ ...
В данный момент запрос такой:
SELECT *, CONCAT(title,' ',forename,' ',surname) AS name
FROM customer c
INNER JOIN customer_data d on c.customer_id=d.customer_id
WHERE name LIKE '%Smith%' LIMIT 10, 20
Кроме того, правильно ли я считаю, что могу использовать CONCAT с LIKE таким образом?
(Я понимаю, что INNER JOIN может быть неправильным типом JOIN для использования. На самом деле я понятия не имею, в чем разница между разными JOIN. Я собираюсь изучить это сейчас!)
Ответы:
Вы можете попробовать следующее:
Обратите внимание, что a
JOIN
- это просто синонимINNER JOIN
.Прецедент:
Результат (запрос без
LIMIT
иWHERE
):источник
Если вы работаете с тяжелыми запросами, вам лучше переместить запрос последней строки в предложение where. Это намного быстрее и выглядит чище.
источник
sql_no_cache set
), тогда как выполнение поиска в объединении заняло несколько секунд. Все еще сбиты с толку, но я имею в виду, что с такими результатами не поспоришь.Предполагая, что столбец автоинкремента в
customer_data
названId
, вы можете сделать:источник
Для тех, кто должен работать с более старой версией MySQL (до 5.0 ish), вы не можете выполнять подзапросы для этого типа запроса. Вот решение, которое я смог сделать, и, похоже, оно отлично сработало.
По сути, это поиск максимального идентификатора вашей таблицы данных, присоединение его к клиенту, а затем присоединение таблицы данных к найденному максимальному идентификатору. Причина этого в том, что выбор максимума группы не гарантирует, что остальные данные совпадают с идентификатором, если вы не присоедините их обратно к себе.
Я не тестировал это на более новых версиях MySQL, но он работает на 4.0.30.
источник
EXPLAIN
что это означает, что здесь используются временная таблица и файловая сортировка. ДобавлениеORDER BY NULL
в конце отсеивает сортировку файлов.SELECT *, MAX(firstData.id), MAX(secondData.id) [...]
. По логике вещей, изменив на,SELECT main.*, firstData2.*, secondData2.*, MAX(firstData.id), MAX(secondData.id), [...]
я смог сделать это значительно быстрее. Это позволяет первым соединениям читать только из индекса, а не читать все данные из первичного индекса. Теперь красивое решение занимает всего 1,9 раза больше времени, чем решение на основе подзапросов.Я знаю, что это старый вопрос, но на протяжении многих лет ему уделялось много внимания, и я думаю, что ему не хватает концепции, которая может помочь кому-то в аналогичном случае. Я добавляю его сюда для полноты картины.
Если вы не можете изменить исходную схему базы данных, значит, было предоставлено много хороших ответов, которые отлично решают проблему.
Однако, если вы можете изменить свою схему, я бы посоветовал добавить в свою
customer
таблицу поле , содержащееid
последнююcustomer_data
запись для этого клиента:Запрос клиентов
Запросы настолько просты и быстры, насколько это возможно:
Недостатком является дополнительная сложность при создании или обновлении клиента.
Обновление клиента
Каждый раз, когда вы хотите обновить клиента, вы вставляете новую запись в
customer_data
таблицу и обновляетеcustomer
запись.Создание клиента
Создание клиента - это просто вопрос вставки
customer
записи, а затем выполнения тех же операторов:Подведение итогов
Дополнительная сложность создания / обновления клиента может быть пугающей, но ее можно легко автоматизировать с помощью триггеров.
Наконец, если вы используете ORM, этим очень легко управлять. ORM может позаботиться о вставке значений, обновлении идентификаторов и автоматическом объединении двух таблиц за вас.
Вот как
Customer
будет выглядеть ваша изменяемая модель:И ваша неизменяемая
CustomerData
модель, содержащая только геттеры:источник
я думаю, вам нужно изменить c.customer_id на c.id
иначе обновить структуру таблицы
источник
Вы также можете сделать это
источник
Это хорошая идея, записывать фактические данные в таблицу « customer_data ». С этими данными вы можете выбрать все данные из таблицы «customer_data» по своему желанию.
источник