programing

마지막 개별 레코드 세트 가져오기

goodsources 2022. 11. 29. 21:49
반응형

마지막 개별 레코드 세트 가져오기

다음 열이 포함된 데이터베이스 테이블이 있습니다.

id   code   value   datetime   timestamp

이 표에서는 고유한 값만 ID(예: 기본 키)에 있습니다.

날짜/시간 값을 기준으로 이 테이블의 마지막 고유 레코드 집합을 검색합니다.예를 들어, 아래가 내 테이블이라고 합시다.

id   code   value   datetime               timestamp
1    1023   23.56   2011-04-05 14:54:52    1234223421
2    1024   23.56   2011-04-05 14:55:52    1234223423
3    1025   23.56   2011-04-05 14:56:52    1234223424
4    1023   23.56   2011-04-05 14:57:52    1234223425
5    1025   23.56   2011-04-05 14:58:52    1234223426
6    1025   23.56   2011-04-05 14:59:52    1234223427
7    1024   23.56   2011-04-05 15:00:12    1234223428
8    1026   23.56   2011-04-05 15:01:14    1234223429
9    1025   23.56   2011-04-05 15:02:22    1234223430

ID가 4, 7, 8, 9인 레코드, 즉 (날짜 값에 따라) 고유 코드를 가진 마지막 레코드 세트를 가져옵니다.제가 강조하고 있는 것은 제가 달성하려는 것의 예에 불과합니다. 이 표에는 결국 수백만 개의 레코드와 수백 개의 개별 코드 값이 포함됩니다.

이를 위해 어떤 SQL 문을 사용할 수 있습니까?SQL 문 하나로는 할 수 없을 것 같아요.내 데이터베이스는 MySQL 5입니다.

이거면 되겠네요.

 SELECT * 
 FROM [tableName] 
 WHERE id IN (SELECT MAX(id) FROM [tableName] GROUP BY code)

id가 AUTO_INCREMENT인 경우 가장 최근의 datetime도 가장 높은 id를 가지므로 계산 비용이 많이 드는 datetime에 대해 걱정할 필요가 없습니다.

업데이트: 퍼포먼스의 관점에서id ★★★★★★★★★★★★★★★★★」code다수의 레코드를 처리할 때 열이 색인화됩니다. ifid키입니다은 내장되어 만, 「비표준 를 경우가 있습니다.이것은 내장되어 있습니다만, 이 기능을 커버하는 비표준 인덱스를 추가할 필요가 있습니다.code ★★★★★★★★★★★★★★★★★」id.

이것을 시험해 보세요.

SELECT * 
  FROM <YOUR_TABLE>
 WHERE (code, datetime, timestamp) IN
 (
   SELECT code, MAX(datetime), MAX(timestamp)
     FROM <YOUR_TABLE>
    GROUP BY code
 )

오래된 포스트이지만 큰 테이블을 사용하여 @smdrager의 답변을 테스트하는 것은 매우 느렸습니다.이에 대한 저의 해결책은 "where in"이 아닌 "inner join"을 사용하는 것이었습니다.

SELECT * 
 FROM [tableName] as t1
 INNER JOIN (SELECT MAX(id) as id FROM [tableName] GROUP BY code) as t2
 ON t1.id = t2.id

이거 진짜 빨리 되네.

다음과 같은 것을 시도해 보겠습니다.

select * from table
where id in (
    select id
    from table
    group by code
    having datetime = max(datetime)
)

(실행자: 이것은 테스트되지 않았습니다)

날짜/시간이 큰 행의 ID도 클 경우 smdrager가 제안하는 솔루션이 더 빠릅니다.

의 모든 은 '그러면 안 된다'는하고 있는 것 같습니다.GROUP BY code모든 테이블 위에., 는 이 쿼리는합니다( 「 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 」 「 。EXPLAIN 50개 행이 실행되고 ....GROUP BY code0 절대 받아들일수 없습니다.이치

다만, 여기서 데이터에 관한 지식을 사용할 수 있습니다(「투고용의 마지막 코멘트를 표시합니다」라고 읽습니다).

  • 상위 20개 레코드만 선택하면 됩니다.
  • 최근 X개 레코드에서 동일한 코드를 가진 레코드의 양은 비교적 적습니다(투고 간에 코멘트가 균일한 분포, 최근 코멘트를 모두 받은 "바이러스" 투고는 없습니다).
  • 사용 가능한 레코드의 총량>>>codes > > 취득하는 "상위" 레코드의 양

숫자를 실험하면서 나는 항상 20개의 다른 숫자를 찾을 수 있다는 것을 알아냈다.code마지막 50개의 레코드만 선택한다면요.이 경우 다음 쿼리가 작동합니다(@smdrager 코멘트는 사용할 가능성이 높다는 점에 유의하십시오).id대신datetime)

SELECT id, code
FROM tablename
ORDER BY id DESC 
LIMIT 50

전체 테이블을 확인할 필요가 없기 때문에 마지막 50개 항목만 선택하는 것이 매우 빠릅니다.그리고 남은 건 상위 20명을 골라야 해code50개의 엔트리 중에서요.

50개(100, 500) 요소 세트에 대한 쿼리는 수십만 개의 엔트리가 있는 테이블 전체보다 훨씬 빠릅니다.

원시 SQL "후처리"

SELECT MAX(id) as id, code FROM 
    (SELECT id, code
     FROM tablename
     ORDER BY id DESC 
     LIMIT 50) AS nested 
GROUP BY code
ORDER BY id DESC 
LIMIT 20

이것으로 리스트가 표시됩니다.id는 매우 신속합니다.추가 JOIN을 실행할 경우 이 쿼리를 다른 네스트 쿼리로 지정하여 모든 조인을 수행합니다.

백엔드 측 "후처리"

그 후, 데이터를 프로그래밍 언어로 처리해, 최종 세트에 포함시키는 것은, 구별되는 레코드뿐입니다.code.

일종의 Python 유사 코드:

records = select_simple_top_records(50)
added_codes = set()
top_records = []
for record in records:
    # If record for this code was already found before
    # Note: this is not optimal, better to use structure allowing O(1) search and insert
    if record['code'] in added_codes:
        continue
    # Save record
    top_records.append(record)
    added_codes.add(record['code'])
    # If we found all top-20 required, finish
    if len(top_records) >= 20:
        break

언급URL : https://stackoverflow.com/questions/5554075/get-last-distinct-set-of-records

반응형