2017-02-18 1 views
3

MariaDB는 MySQL에서와 같은 방식으로 작동합니다.이 문제가 발생할 때까지 여러 번 들었습니다.MariaDB의 "GROUP BY"는 MySQL과 다르게 동작합니다

최근에, 나는 MariaDB (XtraDB)에 MySQL의 (이노)에서 응용 프로그램을 복제하는 것을 시도하고있다. MariaDB는 아무 것도 변경하지 않고 MySQL 쿼리를 실행하지만 두 플랫폼 모두에서 동일한 쿼리가 실제로 상당히 다르게 동작한다는 사실에 놀랐습니다. 특히 ORDER BYGROUP BY입니다. 예를 들어

:

MyTable 
    ======= 
    +----+----------+---------------------+-----------+ 
    | id | parentId | creationDate  | name  | 
    +----+----------+---------------------+-----------+ 
    | 1 | 2357  | 2017-01-01 06:03:40 | Anna  | 
    +----+----------+---------------------+-----------+ 
    | 2 | 5480  | 2017-01-02 07:13:20 | Becky  | 
    +----+----------+---------------------+-----------+ 
    | 3 | 2357  | 2017-01-03 08:20:12 | Christina | 
    +----+----------+---------------------+-----------+ 
    | 4 | 2357  | 2017-01-03 08:20:15 | Dorothy | 
    +----+----------+---------------------+-----------+ 
    | 5 | 5480  | 2017-01-04 09:25:45 | Emma  | 
    +----+----------+---------------------+-----------+ 
    | 6 | 1168  | 2017-01-05 10:30:10 | Fiona  | 
    +----+----------+---------------------+-----------+ 
    | 7 | 5480  | 2017-01-05 10:33:23 | Gigi  | 
    +----+----------+---------------------+-----------+ 
    | 8 | 1168  | 2017-01-06 12:46:34 | Heidi  | 
    +----+----------+---------------------+-----------+ 
    | 9 | 1168  | 2017-01-06 12:46:34 | Irene  | 
    +----+----------+---------------------+-----------+ 
    | 10 | 2357  | 2017-01-07 14:58:37 | Jane  | 
    +----+----------+---------------------+-----------+ 
    | 11 | 2357  | 2017-01-07 14:58:37 | Katy  | 
    +----+----------+---------------------+-----------+ 

기본적으로 제가 쿼리에서 얻고 싶은 것은 최신 기록을 각 그룹에서 (즉 parentId)입니다. 최신, 나는이 MAX (creationDate)와 MAX를 의미하는 세 개의 서로 다른 parentId 값이 있기 때문에 (id)

그래서, 위의 예를 들어, 내가 얻을 수 있었으면하고있다 : 원래

+----+----------+---------------------+-----------+ 
    | id | parentId | creationDate  | name  | 
    +----+----------+---------------------+-----------+ 
    | 11 | 2357  | 2017-01-07 14:58:37 | Katy  | 
    +----+----------+---------------------+-----------+ 
    | 9 | 1168  | 2017-01-06 12:46:34 | Irene  | 
    +----+----------+---------------------+-----------+ 
    | 7 | 5480  | 2017-01-05 10:33:23 | Gigi  | 
    +----+----------+---------------------+-----------+ 

응용 프로그램

SELECT * FROM 
    (SELECT * FROM `MyTable` WHERE `parentId` IN (...) 
    ORDER BY `creationDate` DESC, `id` DESC) AS `t` 
    GROUP BY `parentId`; 

에서 MySQL, 내부 쿼리가 주문하고 다음 외부 쿼리가 resu에서 각 그룹의 첫 번째 얻을 수 있기 때문에이 작품이 패션과 유사한 쿼리를 가지고 내부 질의의 lt. 외부 질의는 기본적으로 내부 질의의 순서에 따른다.

그러나 MariaDB에서 외부 쿼리는 내부 쿼리 결과의 순서를 무시합니다. 대신 MariaDB에서 이것을 얻습니다.

+----+----------+---------------------+-----------+ 
    | id | parentId | creationDate  | name  | 
    +----+----------+---------------------+-----------+ 
    | 1 | 2357  | 2017-01-01 06:03:40 | Anna  | 
    +----+----------+---------------------+-----------+ 
    | 2 | 5480  | 2017-01-02 07:13:20 | Becky  | 
    +----+----------+---------------------+-----------+ 
    | 6 | 1168  | 2017-01-05 10:30:10 | Fiona  | 
    +----+----------+---------------------+-----------+ 

MariaDB에서 동일한 동작을 수행하려면 다음과 같이하십시오. 내가 쿼리를 다시 작성하기 위하여려고하는 경우

SELECT `t1`.* FROM `MyTable` `t1` LEFT JOIN `MyTable` `t2` ON (
     `t1`.`parentId` = `t2`.`parentId` 
    AND `t2`.`parentId` IN (...) 
    AND `t1`.`creationDate` <= `t2`.`creationDate` 
    AND `t1`.`id` < `t2`.`id`) 
) WHERE `t2`.`id` IS NULL; 

지금 문제가 ..., 내가 그들을 수백 다시 작성해야한다 (확실하지 않음이.하지만 정확한 경우) ... 그리고 그들은 몇 가지 방법을 조금 있습니다 비트는 서로 다르다.

여기에 누군가가 최소한의 변경을 가능하게하는 아이디어가 있는지 궁금합니다.

감사합니다.

+0

MySQL의 매뉴얼이를 다룹니다 여기

은 당신이하려고하는 아마 무엇 인 그룹 현명한 최대를 할 수있는 "빠른"방법의 목록입니다. 그리고 3 가지 유효한 솔루션을 제공합니다. 여전히 어려움을 겪고 계시다면 http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-를 참조하십시오. 매우 간단한 - SQL 쿼리 – Strawberry

+0

당신을 위해 mysql과 mariaDB 버전을 확인하고 select 칼럼이 group by clause에 의해 사용 되어야만하는지 확인하십시오. 문제는 only_full_group_by와 관련이 있습니다. 몇 가지 정보를 볼 수 있습니다 https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html – scaisEdge

+0

MySQL 버전은 5.5.52 ... MariaDB 버전은 10.1.21 ... 입니다. MariaDB에서 SET sql_mode = "ONLY_FULL_GROUP_BY"를 실행하려고했지만 아무런 차이가 없습니다. – user2526586

답변

1

첫 번째 쿼리는 아마 MySQL의에서 일하는 것이 있지만 동작은 설명하지 않은 : 당신이 groupid에 의해 그룹화되어 있지만 *와 비 집계 열을 선택하고 그 이외의 집계 열 중의 값이 정의되지 않은입니다 - 당신이 얻는 가치가 처음으로 발생한 가치라면 그것은 단지 "행운의 문제"입니다.

올바른 것으로 간주 될 수 없더라도이 "트릭"이 실패한 것을 본 적이 없다는 사실은 사실입니다. (그리고 여기 stackoverflow에는이 트릭을 사용하도록 제안하는 많은 upvoted 답변이 있습니다.)하지만 MariaDB는 다른 최적화 엔진을 사용하면 MySQL 문서화되지 않은 동작에 의존 할 수 없습니다.

두 번째 쿼리는 약간의 조정이 필요합니다 :

and (
    `t1`.`creationDate` < `t2`.`creationDate` 
    or (
    `t1`.`creationDate` = `t2`.`creationDate` 
    and `t1`.`id` < `t2`.`id` 
) 
) 

먼저 생성 날짜로 주문하기 때문에, 다음 하나 이상의 기록 점유율이 가장 높은 id를 가진 하나를 받고 동일한 작성 날짜 경우.

같은 쿼리를 작성하는 다른 방법이 있습니다.

select * from mytable 
where id in (
    select max(m.id) 
    from mytable m inner join (
    select parentID, max(creationDate) as max_cd 
    from mytable 
    group by ParentID 
) t on m.parentID = t.parentID and m.creationDate = t.max_cd 
    group by m.parentID, m.creationDate 
) 

그러나 모든 쿼리는 별도로 다시 작성해야합니다. 당신이에서 CreationDate 및 ID를 모두 주문되기 때문에

편집

귀하의 예는 좀 더 복잡하다. 내가 더 잘 설명하게 해줘.

select t.parentID, t.max_cd, max(t.id) as max_id 
from 
    MyTable t inner join ( 
    select parentID, max(creationDate) as max_cd 
    from MyTable 
    group by parentID 
) t1 on t.parentID = t1.parentID and t.creationDate = t1.max_cd 
group t.parentID, t.max_cd 

후 모든 기록을 얻을 수있다 : 당신이 가장 높은 ID를 얻을 수있는 모든 최대에서 CreationDate를 위해 다음

select parentID, max(creationDate) as max_cd 
from MyTable 
group by parentID 

: 우선 모든 parentID 당신은 마지막에서 CreationDate를 얻을 수 있고,해야 할 일 여기서 id는이 쿼리에 의해 반환됩니다. 이 특정 상황에서 테이블 자체의 LEFT JOIN은 쓰기 쉽고 성능이 좋아야합니다.

+0

완전히 이해했는지 모르겠다. 제안 사항을 사용하여 예제 SQL을 다시 작성하면 이것이 맞을 까? SELECT * FROM'MyTable' WHERE'id' IN ( \t SELECT MAX ('id') FROM'MyTable' WHERE'parentId' IN (...) GROUP BY'creationDate' HAVING'creationDate' = MAX ') ) GROUP BY'parentId'; – user2526586

+0

감사합니다. 도움이됩니다. 이제는 SQLs의 혼란을 파헤쳐 하나 하나를 고쳐야 만합니다 ... – user2526586

2

예, 이것은 링크 전용 답변입니다. 그러나 링크는 MariaDB 사이트에 있습니다. 여기

는 '호환성'의 또 다른 토론입니다 : 기술적으로, 말하기, MySQL의는 ANSI 표준에 대한 확장을 구현

https://mariadb.com/kb/en/mariadb/group-by-trick-has-been-optimized-away/. 나중에 그것을 제거하기로 결정 했으므로 MySQL이 MariaDB로 마이그레이션 한 것으로 나타났습니다. https://mariadb.com/kb/en/mariadb/groupwise-max-in-mariadb/

관련 문제