2009-05-18 2 views
0

나는 이것을 일반적으로 재사용 할 수 있도록 제공하려고 노력할 것입니다.MySQL : 존재하지 않는 데이터에 대한 자리 표시자를 사용하여 요약 테이블 초기화

꽤 큰 MySQL 데이터베이스가있는 사이트를 실행 중입니다. 일부 요약/롤업 테이블을 초기화해야합니다. 예를 들어 축구 통계라고합시다. 같은 데이터베이스에서 여러 개의 축구 리그를 다루기 때문에 많은 사람들이 서로 다른 길이의 게임을합니다. 예를 들어, 실내 축구 리그는 4 분의 1을 뛰는 반면 대부분의 야외 리그는 반으로 재생됩니다.

이 연습에서 중요한 세 개의 테이블이 있습니다. 나는 내가 찾고있는 대답에 대해 중요하지 않다고 생각하는 모든 분야를 수정했다.

GAME 
`game`.id 
`game`.home_team_id 
`game`.away_team_id 
`game`.number_of_periods 

GOAL 
// Records for each goal scored in the game 
`goal`.id 
`goal`.game_id 
`goal`.team_id 
`goal`.period_number 
`goal`.player_id 
`goal`.assist_player_id 

PERIOD_SUMMARY 
`period`.id 
`period`.game_id 
`period`.team_id 
`period`.number 
`period`.goals_scored  

궁극적으로 목표 점수가 매겨 졌는지 여부에 관계없이 기간 요약 테이블에서 재생되는 모든 기간에 대한 기록이 있어야합니다. 이 테이블은 게임 생성시 트리거를 통해 적절한 0으로 채워진 레코드를 추가하고 삽입/업데이트 요청시 발동하여 period_summary 테이블을 업데이트하는 것이 매우 쉽기 때문에 한 번만 초기화하면됩니다.

목표를 모두 그룹화하고 SUM()을 사용하여 기간 요약 테이블을 초기화하는 것은 상당히 쉽습니다. 돈이없는 기간을 "채우는"효율적인 방법을 찾는 데 어려움이 있습니다. '는 t는 목표는 0

으로 득점이 내가 알아 내기가 더 효율적인/쉽게 경우입니다하려고 :

  1. 트리거를 작성하고 0으로 채워진 값으로 전체 period_summary 테이블을 미리 기입 그런 다음 이미 알고있는 쿼리를 실행하여 목표가 채점 된 기간 동안 해당 레코드를 업데이트하십시오.
  2. 목표 테이블에 일치하지 않는 레코드 만 0으로 채우는 다른 방법 (임시 저장 프로 시저일까요?)을 사용하십시오.

답변

3

이미 위치 표시자가 있습니다. SQL에서 "알 수 없음 데이터 용 자리 표시 자"가 null입니다.

값을 알 수없는 열 (null)이있는 행이 있거나 행이 전혀 없기 때문에 외부 조인을 통해 행을 얻을 수 있습니다. 모두 null입니다. 어쨌든 속성 데이터 (기본적으로 비 ID 필드)은 null입니다.

그리고 sum() 집합은 null을 무시합니다.

에 게임 행이 있고 (사전 예약 된 이후) 해당 기간 동안 해당 행이 없습니다 (아직 재생되지 않았기 때문에).

select a.*, sum(b.goals_scored) 
from game a left outer join period b on (b.game_id = a.id) 
group by a.id; 

이 (두 팀)에게 총 목표를 보여줍니다 (당신이 두 게임없이와 게임을 기간 데이터를 포함 할 수 있도록, 외부) 그럼 당신은 기간에 양식 게임을 외부에 가입 할 게임으로; (우리가 알지는 못한다.)

이 쿼리는 완성 된 게임 과 진행중인 게임의 총 목표만을 보여줍니다 하는 기간이 적어도 하나의 재생 된) : 우리는 그 뷰를 사용

create view complete_games as 
select a.* from games a 
where exists (select * from period b 
where b.game_id = a.id and b.number = a.number_of_periods) 

수 있습니다

select a.*, sum(b.goals_scored) 
from game a join period b on (b.game_id = a.id) 
group by a.id; 

이보기는 불완전한 게임을 필터링 (당신은 항상 나중에 사람 전에 초기 기간)을 추가 가정 오직 완료 된 게임 합계 :

select a.*, sum(b.goals_scored) 
from complete_games a join period b on (b.game_id = a.id) 
group by a.id; 

그래서 필요가 사전에 없습니다 채우기, 가장 중요한 필요가 잘못된 데이터를 추가하지 않으려면 트리거가 필요로 필요를 (사실 기간이 아직 재생되지 않은 경우 제로 목표를 주장하지 않습니다) 올바른 데이터로 업데이트하십시오. 데이터가있는 기간을 삽입하기 만하면됩니다.

+0

죄송합니다. 내 설명이 원래 질문에서 혼동 스러울 수 있습니다. 요약 테이블은 아직 존재하지 않으며이 실습의 주요 목표는 데이터로 해당 테이블을 초기화하는 것입니다. 목표가 채점되지 않은 경기 (과거에는)에서 플레이 한 모든 기간에 대해 "0"레코드를 생성해야합니다. – AvatarKava

+0

그래, 내 요점은, "초기화"할 필요가 없다는 것이다. 기간이 끝난 후 데이터가 있으면 레코드를 추가하십시오. – tpdi

+0

나는 이미 플레이 된 게임의 데이터로 테이블을 채우는 것을 의미한다고 말하면서. – AvatarKava

0

ISTM 옵션 1은 분명 쉽습니다. 이미 카운터가 이미 존재한다고 믿을 수 있다면 카운터를 높이는 방법을 이미 알고 있습니다. 옵션 2를 사용한다고 가정하면, 부족한 0을 채우는 것이 더 어려울뿐만 아니라 (나는이 기간의 끝에서 일어난다 고 추정한다), 1을 사용하여 카운터를 시작하는 방법을 찾아야한다. if 이전 엔트리가 없으며 첫 번째 골이 득점되었습니다.

공간 효율성에 관해서는 궁극적으로 디스크에 같은 공간이 필요합니다. 어쨌든 기간이 끝날 때 0을 채우는 것이 약간 더 효율적이지만, 완료 기간이 소요될 공간은 실행 기간의 공간보다 커야합니다.

삽입/업데이트 효율성 : 이미 0이 아닌 카운터가있을 수 있으므로 목표 점수를 얻은 경우 조회를 수행해야합니다. 따라서 게임, 팀 및 기간별로 효율적으로 조회 할 수있는 색인을 만들어야합니다. 항상 업데이트를 수행하는 쿼리가 짧으면 더 효율적이기도합니다.

0

열의 기본값을 설정할 수 있다는 것을 알고 있습니까? 기본 키워드.

예 :

TABLE 사람 ( 나이 INT의 DEFAULT 0, 이름 VARCHAR (35) DEFAULT '밥' )

기본값은 당신이 원하는 것을 CREATE (0 예를 들어) null 대신.

모든 것을 해결하지는 않지만 도움이 될 것입니다.

관련 문제