2011-02-05 5 views
0

다른 행을 기반으로 특정 기준에 따라 특정 행을 업데이트하려고합니다.mysql - 다른 행을 기반으로 행을 업데이트하십시오.

COLUMNS: time    type  genre doubles  triples 
ROW 1: 2010.06.21 12:00 1  1  0   0 
ROW 2: 2010.06.21 12:00 1  2  0   0 
ROW 3: 2010.06.21 12:00 1  1  0   0 
ROW 4: 2010.06.21 12:00 2  3  0   0 
ROW 5: 2010.06.22 12:00 2  2  0   0 
ROW 6: 2010.06.22 12:00 2  3  0   0 
ROW 7: 2010.06.22 12:00 1  1  0   0 

나는 다음과 같은 규칙에 따라 doublestriples 열을 업데이트 할 찾고 있어요 것은 : 테이블은 다음과 같습니다 말할 수 있습니다

1) 만 행을 업데이트 보는 경우 행 사이의 time=timetype=type (예 : 행 1,2,3 및 행 5 & 6).

2) 다음 두 가지 genres 후 1로 doubles 열 변화가 있는지 세가있는 경우와, 또는 다음 SO 예에 대해 1로 triples 열을 변경 행만 간의 상이한 genre 년대의 # 카운트 위의 행 1,2,3의 표는 doubles=1입니다. 왜냐하면 3 개의 행 사이에는 두 개의 장르가 있기 때문입니다. 행 5와 6은 행 사이에 두 개의 다른 장르가 있기 때문에 doubles=1이됩니다.can = 1이고 triples can = 1이지만 둘 다 사용할 수는 없습니다.

자, 내가 생각하기에이 규칙에 기반한 PHP를 작성할 수는 있지만, mysql에서 모든 것을 할 수있는 방법이 있는지 궁금합니다. 나는 항상 당신이 SQL 문에서 할 수있는 양에 놀란 것처럼 보인다.

어쩌면합니다 (doublestriples 컬럼에 대한 두 개의 서로 다른 문) 같은 :

복식 - UPDATE myTable SET (doubles=1) WHERE time=time AND type=type ...하지만 당신은 위의 규칙 # 2를 차지 얼마나 (독특한 장르와 행의 카운트 수).

mysql에서 가능한가요? 아니면 여기 PHP로 바꿀 수 있습니까? 미리

감사

답변

1

물론 하나의 쿼리로 처리 할 수 ​​있습니다.이 샘플 테이블 사용 :

create table duotri (time varchar(100), type int, genre int, doubles int, triples int); 
insert duotri values 
('2010.06.21 12:00' ,1  ,1  ,0   ,0), 
('2010.06.21 12:00' ,1  ,2  ,0   ,0), 
('2010.06.21 12:00' ,1  ,1  ,0   ,0), 
('2010.06.21 12:00' ,2  ,3  ,0   ,0), 
('2010.06.22 12:00' ,2  ,2  ,0   ,0), 
('2010.06.22 12:00' ,2  ,3  ,0   ,0), 
('2010.06.22 12:00' ,1  ,1  ,0   ,0); 

업데이트 구문은 double과 triple을 얻기 위해 GROUPed 형식에 가입해야합니다.

update duotri t1 
inner join (
    select time, type, 
    case when count(distinct genre) = 2 then 1 else 0 end doubles, 
    case when count(distinct genre) = 3 then 1 else 0 end triples 
    from duotri 
    group by time, type) t2 
    on t1.time=t2.time and t1.type=t2.type 
set t1.doubles=t2.doubles, t1.triples = t2.triples; 
+0

감사합니다. 나는 이걸 가지고 약간 놀아서 어떻게 작동하는지 알려 드리겠습니다. – themerlinproject

1

그것은 서브 선택하고 CASE 식 또는 열에 대한 카운트 수를 비교를 이용 가능할 수 있지만, 그것으로 인해 MySQL이시키지 않는다는 사실에 어렵다 subselect에서 갱신중인 테이블을 선택합니다.

당신은 선택에서 쉽게 할 수있는

(당신이 그것을 지정하지 않았기 때문에 나는 테이블을 '기록'의 이름을주는거야 오히려 서식이 텍스트보다 SQL에 샘플을주고 항상 도움이됩니다) :

SELECT r0.id, r0.`time`, r0.`type`, r0.`genre`, 
    COUNT(DISTINCT r1.genre) = 2 AS doubles, 
    COUNT(DISTINCT r1.genre) = 3 AS triples 
    FROM recordings AS r0 
    JOIN recordings AS r1 ON r0.`time`=r1.`time` AND r0.`type`=r1.`type` 
    GROUP BY r0.`id`, r0.`time`, r0.`type`, r0.`genre` 

그런 다음 stored procedure 또는 view의 기초로 사용할 수 있습니다 : 그룹이 자주 변경

ALTER TABLE recordings DROP COLUMN doubles; 
ALTER TABLE recordings DROP COLUMN triples; 
ALTER TABLE recordings ADD id INT PRIMARY KEY AUTO_INCREMENT; 

CREATE VIEW recording_genre_count AS 
SELECT r0.id, r0.`time`, r0.`type`, r0.`genre`, 
    CASE COUNT(DISTINCT r1.genre) WHEN 2 THEN 1 ELSE 0 END AS doubles, 
    CASE COUNT(DISTINCT r1.genre) WHEN 3 THEN 1 ELSE 0 END AS triples 
    FROM recordings AS r0 
    JOIN recordings AS r1 ON r0.`time`=r1.`time` AND r0.`type`=r1.`type` 
    GROUP BY r0.`id`, r0.`time`, r0.`type`, r0.`genre`; 
    --Since the columns of recordings are functionally dependent on recordings.id, 
    --you could use just "GROUP BY r0.id", but the above will work on other 
    -- DBMSs 

경우 뷰는 더 나은 선택이다. 또한 데이터 consistency을 보장합니다. doublestriples 열을 업데이트하는 쿼리를 실행해야하는 경우 행을 삽입 한 직후 DB가 일관성이없는 상태가됩니다 (triggers이 도움이 될 수 있지만 UPDATE의 하위 선택과 마찬가지로 트리거에서 선택하는 데 문제가 있음) 업데이트되는 테이블). 조회수와 검색어는 저장 프로 시저보다 추가 열 (예 : quadruples)을 더 쉽게 허용합니다.

관련 문제