MySQL ПРИСОЕДИНИТЬ самую последнюю строку?
У меня есть клиент таблицы, который хранит customer_id, электронную почту и ссылку. Существует дополнительная таблица customer_data, в которой хранится историческая запись об изменениях, сделанных клиенту, т.е. Когда произошла смена новой строки.
Чтобы отобразить информацию о клиентах в таблице, необходимо соединить две таблицы, однако только к последней таблице из customer_data следует присоединить к таблице клиентов.
Это немного усложняется тем, что запрос разбит на страницы, поэтому имеет предел и смещение.
Как я могу это сделать с MySQL? Я думаю, что я хочу разместить DISTINCT там где-то...
Запрос в минуту выглядит следующим образом:
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. Я сейчас займусь этим!)
Ответы
Ответ 1
Вы можете попробовать следующее:
SELECT CONCAT(title, ' ', forename, ' ', surname) AS name
FROM customer c
JOIN (
SELECT MAX(id) max_id, customer_id
FROM customer_data
GROUP BY customer_id
) c_max ON (c_max.customer_id = c.customer_id)
JOIN customer_data cd ON (cd.id = c_max.max_id)
WHERE CONCAT(title, ' ', forename, ' ', surname) LIKE '%Smith%'
LIMIT 10, 20;
Обратите внимание, что a JOIN
является просто синонимом INNER JOIN
.
Тестовый пример:
CREATE TABLE customer (customer_id int);
CREATE TABLE customer_data (
id int,
customer_id int,
title varchar(10),
forename varchar(10),
surname varchar(10)
);
INSERT INTO customer VALUES (1);
INSERT INTO customer VALUES (2);
INSERT INTO customer VALUES (3);
INSERT INTO customer_data VALUES (1, 1, 'Mr', 'Bobby', 'Smith');
INSERT INTO customer_data VALUES (2, 1, 'Mr', 'Bob', 'Smith');
INSERT INTO customer_data VALUES (3, 2, 'Mr', 'Jane', 'Green');
INSERT INTO customer_data VALUES (4, 2, 'Miss', 'Jane', 'Green');
INSERT INTO customer_data VALUES (5, 3, 'Dr', 'Jack', 'Black');
Результат (запрос без LIMIT
и WHERE
):
SELECT CONCAT(title, ' ', forename, ' ', surname) AS name
FROM customer c
JOIN (
SELECT MAX(id) max_id, customer_id
FROM customer_data
GROUP BY customer_id
) c_max ON (c_max.customer_id = c.customer_id)
JOIN customer_data cd ON (cd.id = c_max.max_id);
+-----------------+
| name |
+-----------------+
| Mr Bob Smith |
| Miss Jane Green |
| Dr Jack Black |
+-----------------+
3 rows in set (0.00 sec)
Ответ 2
Если вы работаете с тяжелыми запросами, лучше переместить запрос для последней строки в предложении where. Это намного быстрее и выглядит чище.
SELECT c.*,
FROM client AS c
LEFT JOIN client_calling_history AS cch ON cch.client_id = c.client_id
WHERE
cch.cchid = (
SELECT MAX(cchid)
FROM client_calling_history
WHERE client_id = c.client_id AND cal_event_id = c.cal_event_id
)
Ответ 3
Предполагая, что столбец автоинкремента в customer_data
называется Id
, вы можете сделать:
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%'
AND d.ID = (
Select Max(D2.Id)
From customer_data As D2
Where D2.customer_id = D.customer_id
)
LIMIT 10, 20
Ответ 4
Для тех, кто должен работать с более старой версией MySQL (pre-5.0 ish), вы не можете выполнять подзапросы для этого типа запросов. Вот решение, которое я смог сделать, и, похоже, он отлично работает.
SELECT MAX(d.id), d2.*, CONCAT(title,' ',forename,' ',surname) AS name
FROM customer AS c
LEFT JOIN customer_data as d ON c.customer_id=d.customer_id
LEFT JOIN customer_data as d2 ON d.id=d2.id
WHERE CONCAT(title, ' ', forename, ' ', surname) LIKE '%Smith%'
GROUP BY c.customer_id LIMIT 10, 20;
По сути, это поиск максимального идентификатора вашей таблицы данных, соединяющего его с клиентом, а затем присоединение к таблице данных к найденному максимальному идентификатору. Причина этого заключается в том, что выбор максимального количества групп не гарантирует, что остальные данные совпадают с идентификатором, если вы не присоедините его к себе.
Я не тестировал это в более новых версиях MySQL, но он работает с 4.0.30.
Ответ 5
SELECT CONCAT(title,' ',forename,' ',surname) AS name * FROM customer c
INNER JOIN customer_data d on c.id=d.customer_id WHERE name LIKE '%Smith%'
Я думаю, вам нужно изменить
c.customer_id - c.id
Структура таблицы обновления else
Ответ 6
Я знаю, что этот вопрос старый, но на протяжении многих лет ему уделялось много внимания, и я думаю, что в нем отсутствует концепция, которая может помочь кому-то в аналогичном случае. Я добавляю это здесь для полноты картины.
Если вы не можете изменить исходную схему базы данных, то было предоставлено много хороших ответов, и проблема решается просто отлично.
Однако если вы можете изменить свою схему, я бы посоветовал добавить в вашу таблицу customer
поле, содержащее id
последней записи customer_data
для этого клиента:
CREATE TABLE customer (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
current_data_id INT UNSIGNED NULL DEFAULT NULL
);
CREATE TABLE customer_data (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
customer_id INT UNSIGNED NOT NULL,
title VARCHAR(10) NOT NULL,
forename VARCHAR(10) NOT NULL,
surname VARCHAR(10) NOT NULL
);
Опрос клиентов
Запросы настолько просты и быстры, насколько это возможно:
SELECT c.*, d.title, d.forename, d.surname
FROM customer c
INNER JOIN customer_data d on d.id = c.current_data_id
WHERE ...;
Недостатком является дополнительная сложность при создании или обновлении клиента.
Обновление клиента
Всякий раз, когда вы хотите обновить клиента, вы вставляете новую запись в таблицу customer_data
и обновляете запись customer
.
INSERT INTO customer_data (customer_id, title, forename, surname) VALUES(2, 'Mr', 'John', 'Smith');
UPDATE customer SET current_data_id = LAST_INSERT_ID() WHERE id = 2;
Создание клиента
Создание клиента - это просто вставка записи customer
, а затем выполнение тех же операторов:
INSERT INTO customer () VALUES ();
SET @customer_id = LAST_INSERT_ID();
INSERT INTO customer_data (customer_id, title, forename, surname) VALUES(@customer_id, 'Mr', 'John', 'Smith');
UPDATE customer SET current_data_id = LAST_INSERT_ID() WHERE id = @customer_id;
Завершение
Дополнительная сложность для создания/обновления клиента может быть пугающей, но ее можно легко автоматизировать с помощью триггеров.
Наконец, если вы используете ORM, этим очень легко управлять. ORM может позаботиться о вставке значений, обновлении идентификаторов и автоматическом соединении двух таблиц.
Вот как будет выглядеть ваша изменяемая модель Customer
:
class Customer
{
private int id;
private CustomerData currentData;
public Customer(String title, String forename, String surname)
{
this.update(title, forename, surname);
}
public void update(String title, String forename, String surname)
{
this.currentData = new CustomerData(this, title, forename, surname);
}
public String getTitle()
{
return this.currentData.getTitle();
}
public String getForename()
{
return this.currentData.getForename();
}
public String getSurname()
{
return this.currentData.getSurname();
}
}
И ваша неизменная модель CustomerData
, которая содержит только геттеры:
class CustomerData
{
private int id;
private Customer customer;
private String title;
private String forename;
private String surname;
public CustomerData(Customer customer, String title, String forename, String surname)
{
this.customer = customer;
this.title = title;
this.forename = forename;
this.surname = surname;
}
public String getTitle()
{
return this.title;
}
public String getForename()
{
return this.forename;
}
public String getSurname()
{
return this.surname;
}
}
Ответ 7
Это хорошая идея, что ведение фактических данных в таблице customer_datastrong > . С помощью этих данных вы можете выбрать все данные из таблицы "customer_data", как вы пожелаете.
Ответ 8
Это может помочь
Как выбрать самый последний набор датированных записей из таблицы mysql
Вы можете использовать подзапрос, чтобы получить самую последнюю запись, а затем присоединиться к вашему клиенту.
Ответ 9
Вы также можете сделать это
SELECT CONCAT(title, ' ', forename, ' ', surname) AS name
FROM customer c
LEFT JOIN (
SELECT * FROM customer_data ORDER BY id DESC
) customer_data ON (customer_data.customer_id = c.customer_id)
GROUP BY c.customer_id
WHERE CONCAT(title, ' ', forename, ' ', surname) LIKE '%Smith%'
LIMIT 10, 20;