programing

MySQL - 그룹에 의해 반환되는 행을 제어합니다.

itsource 2023. 1. 17. 21:26
반응형

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로 최적화되어 있지 않지만 상관없는 서브쿼리는 메모리가 아닌 디스크에 기록될 정도로 크지 않은 한 나쁘지 않습니다.이 쿼리는 2개의 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);

, , 1회 통과UNIQUE INDEX ON MYTABLE (id, version_id)가지고 계신다면 (제 생각에는)

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

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

임시 테이블은 필요 없습니다.

저는 보통 다음 서브쿼리를 사용합니다.

datatable에서 id, version_id, field1, field2를 dt로 선택합니다(id = 여기서 dt.id에서 version_id 설명 제한 1로 정렬).

이것은 의사 코드이지만, 이와 같은 것은 정상적으로 동작합니다.

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

언제든지 분석 기능을 사용할 수 있으므로 제어력이 향상됩니다.

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

데이터 유형에 따라 랭크() 함수의 문제가 발생할 경우 row_number() 또는 dense_rank() 중에서 선택할 수 있습니다.

이게 네가 원하는 거라고 생각해.

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

거기서 얻은 결과는

1, 2, textb, text2

2, 3, texte, text5

편집: 테이블을 다시 만들고 ID an version_id가 복합 프라이머리 키인 동일한 데이터를 삽입합니다.이것으로 제가 아까 말씀드린 답이 나왔습니다.MySQL에도 있었어요.

테스트하지 않았지만 다음과 같은 기능이 있을 수 있습니다.

MAX(version_id) 설명별 ID 순서별 테이블 그룹에서 * 선택

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

반응형