MySQL JOIN은 가장 최근의 행만 사용하시겠습니까?
customer_id, 이메일, 레퍼런스를 저장하는 테이블 고객이 있습니다.고객 변경 이력(새로운 행이 삽입된 경우)을 저장하는 추가 테이블 customer_data가 있습니다.
테이블에 고객 정보를 표시하려면 2개의 테이블을 결합해야 하지만 customer_data의 최신 행만 고객 테이블에 결합해야 합니다.
쿼리에 페이지 수가 지정되기 때문에 제한과 오프셋이 있다는 점에서 조금 복잡해집니다.
MySQL에서는 어떻게 해야 하나요?어딘가에 DISTRIENT를 넣고 싶은데...
지금 질의는 이렇습니다.
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 with LIKE를 이렇게 사용할 수 있다고 생각하는 것이 맞습니까?
(INSER JOIN은 잘못된 유형의 JOIN일 수 있습니다.사실 JOIN의 차이점이 뭔지 모르겠어요.지금부터 알아보겠습니다!)
다음을 시도해 볼 수 있습니다.
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;
주의: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');
결과(Query without the query)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)
부하가 높은 쿼리를 사용하는 경우 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
)
에서 자동 증가 열 추정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
이전 버전의 MySQL(5.0 이전)을 사용해야 하는 사용자는 이 유형의 쿼리에 대한 하위 쿼리를 수행할 수 없습니다.이것이 제가 할 수 있는 해결책입니다.그리고 그것은 잘 되는 것 같았습니다.
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;
기본적으로는 데이터 테이블의 최대 ID를 찾아 고객에게 결합하고 데이터 테이블을 발견된 최대 ID로 결합하는 것입니다.그 이유는 그룹의 최대값을 선택해도 사용자가 ID에 다시 가입하지 않는 한 나머지 데이터가 ID와 일치한다는 보장이 없기 때문입니다.
새로운 버전의 MySQL에서는 테스트하지 않았지만 4.0.30에서는 동작합니다.
이 질문이 오래된 건 알지만, 몇 년 동안 많은 관심을 받아왔기 때문에 비슷한 경우에 도움이 될 수 있는 개념이 빠진 것 같아요.완성도를 높이기 위해 여기에 추가합니다.
원래 데이터베이스 스키마를 수정할 수 없는 경우 많은 좋은 답변이 제공되어 문제를 잘 해결합니다.
단, 스키마를 변경할 수 있다면, 당신의 스키마에 필드를 추가하는 것이 좋습니다.customer
「」를 유지하는 id
customer_data
: "Discustomer" " "Discustomer :
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은 값 삽입, ID 업데이트 및 2개의 테이블 결합을 자동으로 수행할 수 있습니다.
은 입니다.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
포함된 getter:
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;
}
}
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으로 변경해야 합니다.
그렇지 않으면 테이블 구조 업데이트
이것도 할 수 있어요.
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;
실제 데이터를 "customer_data" 테이블에 기록하는 것이 좋습니다.이 데이터를 사용하여 "customer_data" 테이블에서 원하는 모든 데이터를 선택할 수 있습니다.
왼쪽에서 가장 최근 행 1개에 쉽게 가입할 수 있는 Select over ON 문구를 사용합니다.
SELECT *
FROM A
LEFT JOIN B
ON A.id = (SELECT MAX(id) FROM B WHERE id = A.id)
여기서 A.id은 자동 증분 프라이머리 키입니다.
언급URL : https://stackoverflow.com/questions/3619030/mysql-join-the-most-recent-row-only
'source' 카테고리의 다른 글
변수를 사용하는 인덱스가 있는 경우 MySQL 순위 지정 (0) | 2023.01.19 |
---|---|
MySQL에서 utf8 깨진 문자 감지 (0) | 2023.01.19 |
프라이머리 키 없이 테이블을 만들고 프라이머리 키를 추가할 경우 프라이머리 키는 클러스터된 인덱스입니까? (0) | 2023.01.15 |
하위 쿼리에서 WHERE를 삭제할 수 없습니다. (0) | 2023.01.15 |
서버를 재부팅하지 않고 .env 변수 새로고침(Larabel 5, 공유 호스팅) (0) | 2023.01.15 |