복붙노트

[SQL] 각 그룹의 마지막 레코드를 가져 - MySQL의

SQL

각 그룹의 마지막 레코드를 가져 - MySQL의

아래와 같이 데이터를 포함하는 테이블에 메시지가 있습니다 :

Id   Name   Other_Columns
-------------------------
1    A       A_data_1
2    A       A_data_2
3    A       A_data_3
4    B       B_data_1
5    B       B_data_2
6    C       C_data_1

내가 이름으로 메시지 그룹에서 쿼리를 선택 *를 실행하면, 나는 결과를 얻을 것이다 :

1    A       A_data_1
4    B       B_data_1
6    C       C_data_1

어떤 쿼리는 다음과 같은 결과를 반환합니다?

3    A       A_data_3
5    B       B_data_2
6    C       C_data_1

즉, 각 그룹의 마지막 레코드가 반환해야합니다.

현재, 이것은 내가 사용하는 쿼리는 다음과 같습니다

SELECT
  *
FROM (SELECT
  *
FROM messages
ORDER BY id DESC) AS x
GROUP BY name

그러나 이것은 매우 비효율적 보인다. 다른 방법은 같은 결과를 달성하기 위해?

해결법

  1. ==============================

    1.MySQL의 8.0는 이제 거의 모든 인기있는 SQL 구현과 같은 기능을 윈도 지원합니다. 이 표준 문법, 우리는 가장 큰-N 당 그룹 쿼리를 작성할 수 있습니다 :

    MySQL의 8.0는 이제 거의 모든 인기있는 SQL 구현과 같은 기능을 윈도 지원합니다. 이 표준 문법, 우리는 가장 큰-N 당 그룹 쿼리를 작성할 수 있습니다 :

    WITH ranked_messages AS (
      SELECT m.*, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id DESC) AS rn
      FROM messages AS m
    )
    SELECT * FROM ranked_messages WHERE rn = 1;
    

    아래는 제가 2009 년에이 질문에 대해 쓴 원래의 대답은 :

    나는 해결책이 방법을 쓰기 :

    SELECT m1.*
    FROM messages m1 LEFT JOIN messages m2
     ON (m1.name = m2.name AND m1.id < m2.id)
    WHERE m2.id IS NULL;
    

    성능, 하나 개의 솔루션 또는 다른와 관련하여 데이터의 특성에 따라 더 좋을 수 있습니다. 당신은 두 쿼리를 테스트하고 데이터베이스 주어진 성능에서 더 나은 하나를 사용해야합니다 그래서.

    예를 들어, 나는 StackOverflow의 당당한 데이터 덤프의 사본을 가지고있다. 나는 벤치마킹을 위해 그것을 사용합니다. 소식 테이블에 1,114,357 행이 있습니다. 이것은 나의 맥북 프로 2.40GHz에서 MySQL 5.0.75에서 실행되고 있습니다.

    나는 주어진 사용자 ID (광산)에 대한 가장 최근의 게시물을 찾기 위해 쿼리를 작성할 수 있습니다.

    첫 번째 하위 쿼리에서 그룹 BY와 @Eric에 의해 표시되는 기술을 사용하여 :

    SELECT p1.postid
    FROM Posts p1
    INNER JOIN (SELECT pi.owneruserid, MAX(pi.postid) AS maxpostid
                FROM Posts pi GROUP BY pi.owneruserid) p2
      ON (p1.postid = p2.maxpostid)
    WHERE p1.owneruserid = 20860;
    
    1 row in set (1 min 17.89 sec)
    

    심지어는 분석을 16 초 동안 소요 EXPLAIN :

    +----+-------------+------------+--------+----------------------------+-------------+---------+--------------+---------+-------------+
    | id | select_type | table      | type   | possible_keys              | key         | key_len | ref          | rows    | Extra       |
    +----+-------------+------------+--------+----------------------------+-------------+---------+--------------+---------+-------------+
    |  1 | PRIMARY     | <derived2> | ALL    | NULL                       | NULL        | NULL    | NULL         |   76756 |             | 
    |  1 | PRIMARY     | p1         | eq_ref | PRIMARY,PostId,OwnerUserId | PRIMARY     | 8       | p2.maxpostid |       1 | Using where | 
    |  2 | DERIVED     | pi         | index  | NULL                       | OwnerUserId | 8       | NULL         | 1151268 | Using index | 
    +----+-------------+------------+--------+----------------------------+-------------+---------+--------------+---------+-------------+
    3 rows in set (16.09 sec)
    

    지금 가입 LEFT 내 기술을 사용하여 동일한 쿼리 결과를 생성 :

    SELECT p1.postid
    FROM Posts p1 LEFT JOIN posts p2
      ON (p1.owneruserid = p2.owneruserid AND p1.postid < p2.postid)
    WHERE p2.postid IS NULL AND p1.owneruserid = 20860;
    
    1 row in set (0.28 sec)
    

    두 테이블은 자신의 인덱스를 사용 할 수있는 분석 프로그램을 EXPLAIN :

    +----+-------------+-------+------+----------------------------+-------------+---------+-------+------+--------------------------------------+
    | id | select_type | table | type | possible_keys              | key         | key_len | ref   | rows | Extra                                |
    +----+-------------+-------+------+----------------------------+-------------+---------+-------+------+--------------------------------------+
    |  1 | SIMPLE      | p1    | ref  | OwnerUserId                | OwnerUserId | 8       | const | 1384 | Using index                          | 
    |  1 | SIMPLE      | p2    | ref  | PRIMARY,PostId,OwnerUserId | OwnerUserId | 8       | const | 1384 | Using where; Using index; Not exists | 
    +----+-------------+-------+------+----------------------------+-------------+---------+-------+------+--------------------------------------+
    2 rows in set (0.00 sec)
    

    여기에 내 게시물 테이블에 대한 DDL이다 :

    CREATE TABLE `posts` (
      `PostId` bigint(20) unsigned NOT NULL auto_increment,
      `PostTypeId` bigint(20) unsigned NOT NULL,
      `AcceptedAnswerId` bigint(20) unsigned default NULL,
      `ParentId` bigint(20) unsigned default NULL,
      `CreationDate` datetime NOT NULL,
      `Score` int(11) NOT NULL default '0',
      `ViewCount` int(11) NOT NULL default '0',
      `Body` text NOT NULL,
      `OwnerUserId` bigint(20) unsigned NOT NULL,
      `OwnerDisplayName` varchar(40) default NULL,
      `LastEditorUserId` bigint(20) unsigned default NULL,
      `LastEditDate` datetime default NULL,
      `LastActivityDate` datetime default NULL,
      `Title` varchar(250) NOT NULL default '',
      `Tags` varchar(150) NOT NULL default '',
      `AnswerCount` int(11) NOT NULL default '0',
      `CommentCount` int(11) NOT NULL default '0',
      `FavoriteCount` int(11) NOT NULL default '0',
      `ClosedDate` datetime default NULL,
      PRIMARY KEY  (`PostId`),
      UNIQUE KEY `PostId` (`PostId`),
      KEY `PostTypeId` (`PostTypeId`),
      KEY `AcceptedAnswerId` (`AcceptedAnswerId`),
      KEY `OwnerUserId` (`OwnerUserId`),
      KEY `LastEditorUserId` (`LastEditorUserId`),
      KEY `ParentId` (`ParentId`),
      CONSTRAINT `posts_ibfk_1` FOREIGN KEY (`PostTypeId`) REFERENCES `posttypes` (`PostTypeId`)
    ) ENGINE=InnoDB;
    
  2. ==============================

    2.UPD : 2017년 3월 31일, MySQL을 5.7.5이 ONLY_FULL_GROUP_BY 스위치를 만든 버전 (따라서, 쿼리 BY 비 결정적 그룹이 비활성화되었습니다) 기본적으로 사용 가능. 또한, 그들은 구현하여 GROUP 업데이트, 심지어 장애인 스위치를 더 이상 예상대로 솔루션은 작동하지 않을 수 있습니다. 하나는 확인해야합니다.

    UPD : 2017년 3월 31일, MySQL을 5.7.5이 ONLY_FULL_GROUP_BY 스위치를 만든 버전 (따라서, 쿼리 BY 비 결정적 그룹이 비활성화되었습니다) 기본적으로 사용 가능. 또한, 그들은 구현하여 GROUP 업데이트, 심지어 장애인 스위치를 더 이상 예상대로 솔루션은 작동하지 않을 수 있습니다. 하나는 확인해야합니다.

    작품 벌금 위 빌 Karwin의 솔루션은 그룹 내에서 항목 수는 오히려 작은 경우,하지만 그룹이 오히려 큰 경우이 솔루션은 N * N 단의 / 2 + N / 2 NULL 비교 약이 필요하기 때문에 쿼리의 성능이 나쁜됩니다.

    나는 1182 개 그룹과 18,684,446 행의 InnoDB의 테이블에 내 테스트를했다. 표는 작용 성 시험 testresults 포함하고, 기본 키 (test_id, REQUEST_ID)을 갖는다. 따라서 test_id는 기이고 I는 각 test_id 대한 마지막 REQUEST_ID를 검색 하였다.

    빌의 솔루션은 이미 내 델 E4310에 몇 시간 동안 실행되었으며 (따라서 EXPLAIN에서 인덱스를 사용) 커버리지 지수에서 작동에도 불구하고 끝내려고 할 때 나도 몰라.

    저도 같은 생각을 기반으로하는 다른 솔루션의 몇 가지있다 :

    3 가지 방법 MySQL을 사용 인덱스는 몇 가지 세부 사항을 이해할 수있는 좋은 기사입니다.

    해결 방법 1

    이 사람은 믿을 수 없을만큼 빠른, 내 18M + 행에 0.8에 대한 초 걸립니다 :

    SELECT test_id, MAX(request_id) AS request_id
    FROM testresults
    GROUP BY test_id DESC;
    

    당신은 ASC에 순서를 변경 하위 쿼리에 넣어, 그 열의 나머지에 가입하는 부질으로 유일한 식별자 및 사용을 반환하려면 :

    SELECT test_id, request_id
    FROM (
        SELECT test_id, MAX(request_id) AS request_id
        FROM testresults
        GROUP BY test_id DESC) as ids
    ORDER BY test_id;
    

    이 사람은 내 데이터에 1, 2에 대한 초 걸립니다.

    해결 방법 2

    여기 내 테이블에 대한 19초 정도 걸립니다 또 다른 솔루션입니다 :

    SELECT test_id, request_id
    FROM testresults, (SELECT @group:=NULL) as init
    WHERE IF(IFNULL(@group, -1)=@group:=test_id, 0, 1)
    ORDER BY test_id DESC, request_id DESC
    

    그것은뿐만 아니라 내림차순으로 테스트를 반환합니다. 그것은 전체 인덱스 스캔을 수행하지만 어떻게 각 그룹에 대한 출력 N 최대 행 당신에게 아이디어를주고 여기에 있기 때문에 그것은 느린 많이 있습니다.

    쿼리의 단점은 그 결과가 쿼리 캐시 캐시 할 수 없다는 것입니다.

  3. ==============================

    3.당신은 거기 중간이기 때문에, 올바른 그룹을 반환하기 위해 서브 쿼리를 사용합니다.

    당신은 거기 중간이기 때문에, 올바른 그룹을 반환하기 위해 서브 쿼리를 사용합니다.

    이 시도:

    select
        a.*
    from
        messages a
        inner join 
            (select name, max(id) as maxid from messages group by name) as b on
            a.id = b.maxid
    

    당신의 최대를 원하는 경우 그렇지 않은 경우 :

    select
        a.*
    from
        messages a
        inner join 
            (select name, max(other_col) as other_col 
             from messages group by name) as b on
            a.name = b.name
            and a.other_col = b.other_col
    

    이 방법을 사용하면 매우 느린 / 비효율적 인 경향이 귀하의 하위 쿼리에 상관 하위 쿼리 및 / 또는 주문을 피하십시오.

  4. ==============================

    4.그럼, 각 그룹 내 마지막 게시물에 대한 ID를 얻을 WHERE X의 구조에 대한 인수로 첫 번째 쿼리의 결과를 사용하여 메시지 테이블에서 선택하는 다른 솔루션에 도착했다 :

    그럼, 각 그룹 내 마지막 게시물에 대한 ID를 얻을 WHERE X의 구조에 대한 인수로 첫 번째 쿼리의 결과를 사용하여 메시지 테이블에서 선택하는 다른 솔루션에 도착했다 :

    SELECT id, name, other_columns
    FROM messages
    WHERE id IN (
        SELECT MAX(id)
        FROM messages
        GROUP BY name
    );
    

    나는이 수행은 다른 솔루션의 일부에 비해 방법을 모른다, 그러나 3+ 백만 행 내 테이블 화려했다. (1200+ 결과 4 번째 실행)

    이것은 MySQL과 SQL 서버에서 모두 작동합니다.

  5. ==============================

    5.서브 쿼리 바이올린 링크에 의해 해결

    서브 쿼리 바이올린 링크에 의해 해결

    select * from messages where id in
    (select max(id) from messages group by Name)
    

    해결 방법으로는 조건 바이올린 링크를 가입

    select m1.* from messages m1 
    left outer join messages m2 
    on ( m1.id<m2.id and m1.name=m2.name )
    where m2.id is null
    

    이 게시물에 대한 이유는 바이올린 링크 만 제공하는 것입니다. 같은 SQL은 이미 다른 답변에서 제공됩니다.

  6. ==============================

    6.다음과 같이 상당한 속도로 접근 방법이다.

    다음과 같이 상당한 속도로 접근 방법이다.

    SELECT * 
    FROM messages a
    WHERE Id = (SELECT MAX(Id) FROM messages WHERE a.Name = Name)
    

    결과

    Id  Name    Other_Columns
    3   A   A_data_3
    5   B   B_data_2
    6   C   C_data_1
    
  7. ==============================

    7.여기에 두 가지 제안 사항입니다. 첫째, MySQL의 지원에 ROW_NUMBER ()가, 매우 간단 경우 :

    여기에 두 가지 제안 사항입니다. 첫째, MySQL의 지원에 ROW_NUMBER ()가, 매우 간단 경우 :

    WITH Ranked AS (
      SELECT Id, Name, OtherColumns,
        ROW_NUMBER() OVER (
          PARTITION BY Name
          ORDER BY Id DESC
        ) AS rk
      FROM messages
    )
      SELECT Id, Name, OtherColumns
      FROM messages
      WHERE rk = 1;
    

    난 당신이 아이디 위해 마지막 말은 "마지막"에 의해 있으리라 믿고있어. 그렇지 않을 경우, 그에 따라 ROW_NUMBER () 윈도우의 ORDER BY 절을 변경합니다. ROW_NUMBER ()를 사용할 수없는 경우, 이것은 또 다른 솔루션입니다 :

    그렇지 않은 경우 둘째,이 종종 진행하는 좋은 방법입니다 :

    SELECT
      Id, Name, OtherColumns
    FROM messages
    WHERE NOT EXISTS (
      SELECT * FROM messages as M2
      WHERE M2.Name = messages.Name
      AND M2.Id > messages.Id
    )
    

    더 같은 이름을 가진 이후-ID 메시지가있는 경우 즉, 메시지를 선택합니다.

  8. ==============================

    8.아직 많은 DB 테스트 적이 없다하지만 난이 테이블을 조인보다 빠를 수 있다고 생각 :

    아직 많은 DB 테스트 적이 없다하지만 난이 테이블을 조인보다 빠를 수 있다고 생각 :

    SELECT *, Max(Id) FROM messages GROUP BY Name
    
  9. ==============================

    9.다음 목록에서 레코드 하나를 선택하는 또 다른 의해 주문 GROUP_CONCAT를 사용하여 마지막으로 관련 기록을 얻을 수있는 방법과 SUBSTRING_INDEX입니다

    다음 목록에서 레코드 하나를 선택하는 또 다른 의해 주문 GROUP_CONCAT를 사용하여 마지막으로 관련 기록을 얻을 수있는 방법과 SUBSTRING_INDEX입니다

    SELECT 
      `Id`,
      `Name`,
      SUBSTRING_INDEX(
        GROUP_CONCAT(
          `Other_Columns` 
          ORDER BY `Id` DESC 
          SEPARATOR '||'
        ),
        '||',
        1
      ) Other_Columns 
    FROM
      messages 
    GROUP BY `Name` 
    

    쿼리 의지 그룹 이름이 같은 그룹에 내가 사용한 내 경우에는 제공된 구분하여 내림차순으로 특정 그룹의 모든 Other_Columns에 참여합니다 아이디 DESC BY ORDER를 사용하여 모든 Other_Columns 위 || 이 목록을 통해 SUBSTRING_INDEX를 사용하는 최초의 하나를 선택합니다

  10. ==============================

    10.분명히 같은 결과를 얻는 다른 많은 방법이있다, 당신의 질문은 MySQL의 각 그룹의 마지막 결과를 얻는하는 효율적인 방법이 무엇인지 것 같다. 당신은 엄청난 양의 데이터로 작업하고 MySQL의의도 최신 버전으로 이노를 사용하는 가정하는 경우 (예 : 5.7.21 및 8.0.4-RC로) 다음이 일을하는 효율적인 방법이되지 않을 수 있습니다.

    분명히 같은 결과를 얻는 다른 많은 방법이있다, 당신의 질문은 MySQL의 각 그룹의 마지막 결과를 얻는하는 효율적인 방법이 무엇인지 것 같다. 당신은 엄청난 양의 데이터로 작업하고 MySQL의의도 최신 버전으로 이노를 사용하는 가정하는 경우 (예 : 5.7.21 및 8.0.4-RC로) 다음이 일을하는 효율적인 방법이되지 않을 수 있습니다.

    우리는 때로는 60 개 이상의 백만 행이있는 테이블이 작업을 수행해야합니다.

    이 예를 들어 나는 쿼리가 데이터의 모든 그룹에 대한 결과를 찾을 필요가 약 150 만 개 행이 데이터를 사용합니다. 우리의 실제 경우에 우리는 종종 (가설 필요가 매우 많은 데이터를 검사하지 않을) 2000에 대한 그룹에서 데이터를 다시 반환해야합니다.

    나는 다음과 같은 테이블을 사용합니다 :

    CREATE TABLE temperature(
      id INT UNSIGNED NOT NULL AUTO_INCREMENT, 
      groupID INT UNSIGNED NOT NULL, 
      recordedTimestamp TIMESTAMP NOT NULL, 
      recordedValue INT NOT NULL,
      INDEX groupIndex(groupID, recordedTimestamp), 
      PRIMARY KEY (id)
    );
    
    CREATE TEMPORARY TABLE selected_group(id INT UNSIGNED NOT NULL, PRIMARY KEY(id)); 
    

    온도 표는 150 만에 대한 임의의 기록으로 채워, 100 개 다른 그룹으로한다. selected_group는 그 100 개 그룹으로 채워집니다 (우리의 경우에 이것은 일반적으로 모든 그룹에 대한 20 % 미만이 될 것이다).

    이 데이터가 랜덤으로 복수 행 동일한 recordedTimestamps을 가질 수 있다는 것을 의미한다. 우리가 원하는 것은 각 그룹의 마지막 recordedTimestamp와 그룹 ID의 순서로 선택된 모든 그룹의 목록을 얻을 수 있으며, 같은 그룹은 해당 행의 다음 마지막으로 일치 ID로 하나 이상의 일치하는 행이있는 경우.

    가설 MySQL은 BY 절 특별 주문에 마지막 행에서 값을 반환 마지막 () 함수를 가지고 있다면 우리는 간단하게 할 수있는 :

    SELECT 
      last(t1.id) AS id, 
      t1.groupID, 
      last(t1.recordedTimestamp) AS recordedTimestamp, 
      last(t1.recordedValue) AS recordedValue
    FROM selected_group g
    INNER JOIN temperature t1 ON t1.groupID = g.id
    ORDER BY t1.recordedTimestamp, t1.id
    GROUP BY t1.groupID;
    

    이는 단지이 기능에 의해 정상 군을 사용하지 않기 때문에이 경우에는 몇 백 개 행을 검사해야합니다. 이 0 초 단위로 실행하고, 따라서 고효율 될 것이다. 일반적으로 MySQL의에서 우리가 다음이 그룹을 주문 될 수는 GROUP BY 후 있다면 그러나 조항으로이 순서는, 마지막 () 함수의 순서를 결정하는 데 사용되는 GROUP BY 절 다음 ORDER BY 절을 볼 것입니다 참고. BY 절에는 GROUP가없는 경우, 마지막 값이 반환 된 모든 행에서 동일합니다.

    그러나 MySQL은이 있고 이들 중 어느 것도 효율적인없는 증명 않는 어떤 다른 생각에이 그렇게하자 모습을 가지고 있지 않습니다.

    예 1

    SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue
    FROM selected_group g
    INNER JOIN temperature t1 ON t1.id = (
      SELECT t2.id
      FROM temperature t2 
      WHERE t2.groupID = g.id
      ORDER BY t2.recordedTimestamp DESC, t2.id DESC
      LIMIT 1
    );
    

    이 3,009,254 행을 검사하고 8.0.4-RC에 약간 이상 5.7.21에 ~ 0.859 초 걸렸 및

    예 2

    SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue 
    FROM temperature t1
    INNER JOIN ( 
      SELECT max(t2.id) AS id   
      FROM temperature t2
      INNER JOIN (
        SELECT t3.groupID, max(t3.recordedTimestamp) AS recordedTimestamp
        FROM selected_group g
        INNER JOIN temperature t3 ON t3.groupID = g.id
        GROUP BY t3.groupID
      ) t4 ON t4.groupID = t2.groupID AND t4.recordedTimestamp = t2.recordedTimestamp
      GROUP BY t2.groupID
    ) t5 ON t5.id = t1.id;
    

    이 1,505,331 행을 검사하고 8.0.4-RC에 약간 이상 5.7.21에 ~ 1.25 초 걸렸 및

    예 3

    SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue 
    FROM temperature t1
    WHERE t1.id IN ( 
      SELECT max(t2.id) AS id   
      FROM temperature t2
      INNER JOIN (
        SELECT t3.groupID, max(t3.recordedTimestamp) AS recordedTimestamp
        FROM selected_group g
        INNER JOIN temperature t3 ON t3.groupID = g.id
        GROUP BY t3.groupID
      ) t4 ON t4.groupID = t2.groupID AND t4.recordedTimestamp = t2.recordedTimestamp
      GROUP BY t2.groupID
    )
    ORDER BY t1.groupID;
    

    이 3,009,685 행을 검사하고 8.0.4-RC에 약간 이상 5.7.21에 ~ 1.95 초 걸렸 및

    예 4

    SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue
    FROM selected_group g
    INNER JOIN temperature t1 ON t1.id = (
      SELECT max(t2.id)
      FROM temperature t2 
      WHERE t2.groupID = g.id AND t2.recordedTimestamp = (
          SELECT max(t3.recordedTimestamp)
          FROM temperature t3 
          WHERE t3.groupID = g.id
        )
    );
    

    이 6,137,810 행을 검사하고 8.0.4-RC에 약간 이상 5.7.21에 ~ 2.2 초가 소요 및

    예 5

    SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue
    FROM (
      SELECT 
        t2.id, 
        t2.groupID, 
        t2.recordedTimestamp, 
        t2.recordedValue, 
        row_number() OVER (
          PARTITION BY t2.groupID ORDER BY t2.recordedTimestamp DESC, t2.id DESC
        ) AS rowNumber
      FROM selected_group g 
      INNER JOIN temperature t2 ON t2.groupID = g.id
    ) t1 WHERE t1.rowNumber = 1;
    

    이 6,017,808 행을 검사하고 8.0.4-RC에 ~ 4.2 초 걸렸습니다

    예 6

    SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue 
    FROM (
      SELECT 
        last_value(t2.id) OVER w AS id, 
        t2.groupID, 
        last_value(t2.recordedTimestamp) OVER w AS recordedTimestamp, 
        last_value(t2.recordedValue) OVER w AS recordedValue
      FROM selected_group g
      INNER JOIN temperature t2 ON t2.groupID = g.id
      WINDOW w AS (
        PARTITION BY t2.groupID 
        ORDER BY t2.recordedTimestamp, t2.id 
        RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
      )
    ) t1
    GROUP BY t1.groupID;
    

    이 6,017,908 행을 검사하고 8.0.4-RC에 ~ 17.5 초 걸렸습니다

    예 7

    SELECT t1.id, t1.groupID, t1.recordedTimestamp, t1.recordedValue 
    FROM selected_group g
    INNER JOIN temperature t1 ON t1.groupID = g.id
    LEFT JOIN temperature t2 
      ON t2.groupID = g.id 
      AND (
        t2.recordedTimestamp > t1.recordedTimestamp 
        OR (t2.recordedTimestamp = t1.recordedTimestamp AND t2.id > t1.id)
      )
    WHERE t2.id IS NULL
    ORDER BY t1.groupID;
    

    내가 죽일했다, 그래서이 사람은 영원히 가고 있었다.

  11. ==============================

    11.우리는 당신이 기록함으로써 그룹의 마지막 레코드를 받고에서 MySQL을 사용하는 방법을 살펴볼 것이다. 예를 들어, 당신은 게시물의 결과 집합이있는 경우.

    우리는 당신이 기록함으로써 그룹의 마지막 레코드를 받고에서 MySQL을 사용하는 방법을 살펴볼 것이다. 예를 들어, 당신은 게시물의 결과 집합이있는 경우.

    1 개 1 제목 1

    2 1 제목 2

    3 1 제목 3

    4 2 제목 4

    5 2 제목 5

    6 세 제목 6

    나는 제목 3 제목 5 제목 6. 당신은 MySQL의 그룹으로 키보드를 사용하는 카테고리별로 게시물을 얻으려면 각각의 카테고리에서 마지막 게시물을 얻을 수 있어야합니다.

    CATEGORY_ID 게시물 그룹 SELECT * FROM

    이 쿼리가에서 그러나 결과는 우리가 다시 얻을.

    1 개 1 제목 1

    4 2 제목 4

    6 세 제목 6

    에 의해 그룹은 항상 결과 세트에 그룹의 첫 번째 레코드를 반환합니다.

    SELECT ID, CATEGORY_ID, POST_TITLE 게시물 FROM WHERE 아이디 IN (     SELECT MAX (ID)     게시물 FROM     GROUP BY의 CATEGORY_ID );

    이것은 각 그룹에서 가장 높은 ID로 게시물을 반환합니다.

    3 1 제목 3

    5 2 제목 5

    6 세 제목 6

    참조 여기를 클릭하세요

  12. ==============================

    12.

    SELECT 
      column1,
      column2 
    FROM
      table_name 
    WHERE id IN 
      (SELECT 
        MAX(id) 
      FROM
        table_name 
      GROUP BY column1) 
    ORDER BY column1 ;
    
  13. ==============================

    13.여기 내 솔루션입니다 :

    여기 내 솔루션입니다 :

    SELECT 
      DISTINCT NAME,
      MAX(MESSAGES) OVER(PARTITION BY NAME) MESSAGES 
    FROM MESSAGE;
    
  14. ==============================

    14.이 시도:

    이 시도:

    SELECT jos_categories.title AS name,
           joined .catid,
           joined .title,
           joined .introtext
    FROM   jos_categories
           INNER JOIN (SELECT *
                       FROM   (SELECT `title`,
                                      catid,
                                      `created`,
                                      introtext
                               FROM   `jos_content`
                               WHERE  `sectionid` = 6
                               ORDER  BY `id` DESC) AS yes
                       GROUP  BY `yes`.`catid` DESC
                       ORDER  BY `yes`.`created` DESC) AS joined
             ON( joined.catid = jos_categories.id )  
    
  15. ==============================

    15.쿼리는 다음과 같이 읽어야 기본 키에 대한 최신 기록 기초를 가져 오기 위해 다음 자동 증가 기본 키 안녕 @Vijay 데브 테이블 메시지가 이드가 포함되어있는 경우 :

    쿼리는 다음과 같이 읽어야 기본 키에 대한 최신 기록 기초를 가져 오기 위해 다음 자동 증가 기본 키 안녕 @Vijay 데브 테이블 메시지가 이드가 포함되어있는 경우 :

    SELECT m1.* FROM messages m1 INNER JOIN (SELECT max(Id) as lastmsgId FROM messages GROUP BY Name) m2 ON m1.Id=m2.lastmsgId
    
  16. ==============================

    16.당신은 여기뿐만 아니라에서 볼 수 있습니다.

    당신은 여기뿐만 아니라에서 볼 수 있습니다.

    http://sqlfiddle.com/#!9/ef42b/9

    FIRST 솔루션

    SELECT d1.ID,Name,City FROM Demo_User d1
    INNER JOIN
    (SELECT MAX(ID) AS ID FROM Demo_User GROUP By NAME) AS P ON (d1.ID=P.ID);
    

    SECOND SOLUTION

    SELECT * FROM (SELECT * FROM Demo_User ORDER BY ID DESC) AS T GROUP BY NAME ;
    
  17. ==============================

    17.우리는 테이블에서 삭제 중복이 방법을 사용할 수있는 방법이 있습니까? 결과 세트는 우리가 결과 집합에 모든 기록을 삭제할 수 있습니다, 그래서 만약 우리가 효과적으로에는 중복이없는 것, 기본적으로 독특한 기록의 모음입니다? 나는이 시도하지만, MySQL의는 1093 오류를했다.

    우리는 테이블에서 삭제 중복이 방법을 사용할 수있는 방법이 있습니까? 결과 세트는 우리가 결과 집합에 모든 기록을 삭제할 수 있습니다, 그래서 만약 우리가 효과적으로에는 중복이없는 것, 기본적으로 독특한 기록의 모음입니다? 나는이 시도하지만, MySQL의는 1093 오류를했다.

    DELETE FROM messages WHERE id NOT IN
     (SELECT m1.id  
     FROM messages m1 LEFT JOIN messages m2  
     ON (m1.name = m2.name AND m1.id < m2.id)  
     WHERE m2.id IS NULL)
    

    어쩌면 임시 변수에 출력을 저장 한 후 NOT IN (임시 변수)에서 삭제하는 방법이 있나요? 매우 유용한 솔루션 @ 빌 감사합니다.

    편집 : 내가 해결책을 찾은 것 같아요 :

    DROP TABLE IF EXISTS UniqueIDs; 
    CREATE Temporary table UniqueIDs (id Int(11)); 
    
    INSERT INTO UniqueIDs 
        (SELECT T1.ID FROM Table T1 LEFT JOIN Table T2 ON 
        (T1.Field1 = T2.Field1 AND T1.Field2 = T2.Field2 #Comparison Fields  
        AND T1.ID < T2.ID) 
        WHERE T2.ID IS NULL); 
    
    DELETE FROM Table WHERE id NOT IN (SELECT ID FROM UniqueIDs);
    
  18. ==============================

    18.쿼리 아래는 귀하의 질문에 따라 벌금을 작동합니다.

    쿼리 아래는 귀하의 질문에 따라 벌금을 작동합니다.

    SELECT M1.* 
    FROM MESSAGES M1,
    (
     SELECT SUBSTR(Others_data,1,2),MAX(Others_data) AS Max_Others_data
     FROM MESSAGES
     GROUP BY 1
    ) M2
    WHERE M1.Others_data = M2.Max_Others_data
    ORDER BY Others_data;
    
  19. ==============================

    19.각 이름의 마지막 행을 원하는 경우에, 당신은 내림차순으로 ID를 기준으로 각 행의 이름으로 그룹 순서에 행 번호를 제공 할 수 있습니다.

    각 이름의 마지막 행을 원하는 경우에, 당신은 내림차순으로 ID를 기준으로 각 행의 이름으로 그룹 순서에 행 번호를 제공 할 수 있습니다.

    질문

    SELECT t1.Id, 
           t1.Name, 
           t1.Other_Columns
    FROM 
    (
         SELECT Id, 
                Name, 
                Other_Columns,
        (
            CASE Name WHEN @curA 
            THEN @curRow := @curRow + 1 
            ELSE @curRow := 1 AND @curA := Name END 
        ) + 1 AS rn 
        FROM messages t, 
        (SELECT @curRow := 0, @curA := '') r 
        ORDER BY Name,Id DESC 
    )t1
    WHERE t1.rn = 1
    ORDER BY t1.Id;
    
  20. ==============================

    20.

    SELECT * FROM table_name WHERE primary_key IN (SELECT MAX(primary_key) FROM table_name GROUP BY column_name )
    
  21. ==============================

    21.**

    **

    안녕하세요, 쿼리는 도움이 될 수 있습니다 :

    **

    SELECT 
      *
    FROM 
      message 
    
    WHERE 
      `Id` IN (
        SELECT 
          MAX(`Id`) 
        FROM 
          message 
        GROUP BY 
          `Name`
      ) 
    ORDER BY 
       `Id` DESC
    
  22. ==============================

    22.이건 어때:

    이건 어때:

    SELECT DISTINCT ON (name) *
    FROM messages
    ORDER BY name, id DESC;
    

    내가하고 1M 기록 테이블에 (힘든 PostgreSQL을에) 유사한 문제가 있었다. LEFT 함께 하나에 의해 생성 된 44S 조인 대이 용액 1.7s 걸린다. 내 경우에는 내가 0.2 초에 의해 더 나은 성능의 결과로 NULL 값에 대한 사용자 이름 필드의 corrispondant을 필터링 할 수 있었다

  23. ==============================

    23.성능이 우려 정말 경우에 당신은 형 BIT의 IsLastInGroup라는 테이블에 새 열을 도입 할 수 있습니다.

    성능이 우려 정말 경우에 당신은 형 BIT의 IsLastInGroup라는 테이블에 새 열을 도입 할 수 있습니다.

    마지막 인 열을 true로 설정하고 삭제 모든 행의 삽입 / 업데이트 / 그것을 유지. 쓰기가 느려집니다,하지만 당신은 읽기에 혜택을 얻을 것입니다. 그것은 당신의 사용 사례에 따라 달라집니다 그리고 당신이있는 거 읽기에 초점을 맞춘 경우에만하는 것이 좋습니다.

    쿼리에 모양을 따라서 :

    SELECT * FROM Messages WHERE IsLastInGroup = 1
    
  24. ==============================

    24.

    select * from messages group by name desc
    
  25. ==============================

    25.당신이 할 수 계산에 의해 그룹과도 같은 그룹의 마지막 항목을 얻을 :

    당신이 할 수 계산에 의해 그룹과도 같은 그룹의 마지막 항목을 얻을 :

    SELECT 
        user,
        COUNT(user) AS count,
        MAX(id) as last
    FROM request 
    GROUP BY user
    
  26. ==============================

    26.오라클 쿼리 캔의 도움 아래 희망 :

    오라클 쿼리 캔의 도움 아래 희망 :

    WITH Temp_table AS
    (
        Select id, name, othercolumns, ROW_NUMBER() over (PARTITION BY name ORDER BY ID 
        desc)as rank from messages
    )
    Select id, name,othercolumns from Temp_table where rank=1
    
  27. ==============================

    27.또 다른 방법 :

    또 다른 방법 :

    (1 개 프로그램 속성) 각 프로그램 내에서 최대 m2의 가격으로 부동산 찾기 :

    select * from properties p
    join (
        select max(m2_price) as max_price 
        from properties 
        group by program_id
    ) p2 on (p.program_id = p2.program_id)
    having p.m2_price = max_price
    
  28. from https://stackoverflow.com/questions/1313120/retrieving-the-last-record-in-each-group-mysql by cc-by-sa and MIT license