ProgramingTip

MySQL은 가장 최근 행에만 가입 하시겠습니까?

bestdevel 2020. 10. 13. 08:11
반응형

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

추가로, 이런 식으로 LIKE와 함께 CONCAT을 사용할 수 있는지 생각하는 것이 맞습니까?

(INNER 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');

결과 ( 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)

무거운 쿼리로 작업하는 경우 어디에서 최신 행에 대한 요청을 이동하는 것이 좋습니다. 훨씬 빠르고 깨끗해.

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와 일치하는 것을 보장하지 않습니다.

나는 의무 사항 최신 버전의 MySQL에서 테스트하지 않습니다.


나는이 질문이 오래 예는 것을 알고있다 수년에 많은 관심을 받고있는 경우에 누군가를 도울 수있는 개념이 누락되지 않을 것이라고 생각합니다. 완전성을 위해 여기에 추가하겠습니다.

원래의 좋은 지원이 제공되는 문제를 잘 해결했습니다.

이 경우 당신 수 있습니다 , 그러나, 스키마를 수정,의 필드를 당신 추가 할 권합니다 customer보류를 테이블 id최신의 customer_data이 소개 고객에, 대한 write-:

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 업데이트 및 자동으로 두 테이블 결합을 처리 할 수 ​​있습니다.

변경 가능한 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();
    }
}

그리고 CustomerDatagetter 만 포함하는 변경 불가능한 모델 :

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로 변경해야한다고 생각합니다.

그렇지 않으면 테이블 구조를 업데이트합니다.


실제 데이터를 " customer_data "테이블에 로깅하는 것이 좋습니다 . 이 데이터로 "customer_data"테이블에서 원하는 모든 데이터를 선택할 수 있습니다.


이것은 도움이 될 수 있습니다

mysql 테이블에서 가장 최근의 날짜 기록 세트를 선택하는 방법

하위 쿼리를 사용하여 최신 레코드를 가져온 다음 고객과 조인 할 수 있습니다.


당신은 또한 이것을 할 수 있습니다

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;

참고 URL : https://stackoverflow.com/questions/3619030/mysql-join-the-most-recent-row-only

반응형