IT story

MySQL-그룹이 반환하는 행 제어

hot-time 2020. 12. 31. 22:55
반응형

MySQL-그룹이 반환하는 행 제어


다음과 같은 데이터베이스 테이블이 있습니다.

id    version_id    field1    field2
1     1             texta      text1
1     2             textb      text2
2     1             textc      text3
2     2             textd      text4
2     3             texte      text5

해결하지 않았다면 여러 버전의 행과 일부 텍스트 데이터가 포함됩니다.

나는 그것을 쿼리하고 각 ID에 대해 가장 높은 번호를 가진 버전을 반환하고 싶습니다. (따라서 위의 두 번째 및 마지막 행만).

version_id DESC로 주문하는 동안 group by를 사용해 보았지만 그룹화 된 후에 주문하는 것 같아서 작동하지 않습니다.

누구나 아이디어가 있습니까? 할 수 없다고 믿을 수가 없어!

최신 정보:

이것은 작동하지만 하위 쿼리를 사용합니다.

SELECT *
FROM (SELECT * FROM table ORDER BY version_id DESC) t1
GROUP BY t1.id

열의 그룹 별 최대 값 선택이라고합니다. 다음은 mysql에 대한 몇 가지 다른 접근 방식입니다.

방법은 다음과 같습니다.

SELECT *
FROM (SELECT id, max(version_id) as version_id FROM table GROUP BY id) t1
INNER JOIN table t2 on t2.id=t1.id and t1.version_id=t2.version_id

mysql이 서브 쿼리를 위해 메모리에 임시 테이블을 생성하지만 이것은 비교적 효율적입니다. 이 테이블에 대한 (id, version_id)에 대한 인덱스가 이미 있다고 가정합니다.

이러한 유형의 문제에 대해 하위 쿼리를 사용해야하는 것은 SQL의 결함입니다 ( 세미 조인 은 또 다른 예입니다).

하위 쿼리는 mysql에서 잘 최적화되지 않지만 상관 관계가없는 하위 쿼리는 메모리가 아닌 디스크에 기록 될 정도로 크지 않은 한 그렇게 나쁘지 않습니다. 이 쿼리에 int가 두 개뿐이라는 점을 감안할 때 하위 쿼리는 발생하기 훨씬 전에 수백만 행이 될 수 있지만 첫 번째 쿼리의 select * 하위 쿼리는이 문제를 훨씬 빨리 겪을 수 있습니다.


나는 이것이 그것을 할 것이라고 생각하지만 그것이 최고인지 빠른지 확실하지 않습니다.

SELECT * FROM table 
WHERE (id, version_id) IN 
  (SELECT id, MAX(version_id) FROM table GROUP BY id)

SELECT id, version_id, field1, field2
FROM (
    SELECT @prev = id AS st, (@prev := id), m.*
    FROM (
           (SELECT @prev := NULL) p,
           (
            SELECT *
            FROM   mytable
            ORDER BY
                   id DESC, version_id DESC
           ) m
     ) m2
WHERE NOT IFNULL(st, FALSE);

하위 쿼리 없음, 하나가있는 UNIQUE INDEX ON MYTABLE (id, version_id)경우 하나 전달 (내 생각에)


나는 일반적으로 하위 쿼리를 사용합니다.

select id, version_id, field1, field2 from datatable as dt where id = (select id from datatable where id = dt.id order by version_id desc limit 1)


이것은 의사 코드이지만 이와 같은 것이 잘 작동합니다.

select *
from table
inner join
(
    select id , max(version_id) maxVersion
    from table 
) dvtbl ON id = dvtbl.id && versionid = dvtbl.maxVersion

이 쿼리는 다음을 기준으로 그룹없이 작업을 수행합니다.

SELECT * FROM table AS t
LEFT JOIN table AS t2 
    ON t.id=t2.id 
    AND t.version_id < t2.version_id
WHERE t2.id IS NULL

임시 테이블이 필요하지 않습니다.


더 많은 제어를 제공하는 분석 기능도 항상 사용할 수 있습니다.

select tmp.* from ( select id,version_id,field1,field2, rank() over(partition by id order by version_id desc ) as rnk from table) tmp where tmp.rnk=1

데이터 유형에 따라 rank () 함수에 문제가있는 경우 row_number () 또는 density_rank () 중에서 선택할 수도 있습니다.


나는 이것이 당신이 원하는 것이라고 생각합니다.

select id, max(v_id), field1, field2 from table group by id

내가 얻은 결과는

1, 2, textb, text2

2, 3, texte, text5

Edit: I recreated the table and insert the same data with the id an version_id being a compound primary key. This gave the answer I provided earlier. It was also in MySQL.


not tested it but something like this might work:

SELECT * FROM table GROUP BY id ORDER BY MAX(version_id) DESC

ReferenceURL : https://stackoverflow.com/questions/537223/mysql-control-which-row-is-returned-by-a-group-by

반응형