2012-08-27 5 views
1

제가 관리하는 데이터베이스의 테이블에 일부 값을 재배포하고 싶습니다.mysql : 중복 기본 키가있는 정수 값을 추가하십시오.

Firstname(varchar), Lastname(varchar), Date(date), Icecream_consumed(int) 

여기서 이름, 성 및 날짜의 조합은이 테이블의 기본 키를 만듭니다. 이 테이블의 구조를 변경하는 것은 옵션이 아닙니다.

데이터베이스에는 Firstname과 LastName의 총 고유 조합이 80 개 있지만 그 숫자를 5로 낮추고 더 작은 총 Icecream_consumed를 포함한 레코드 중 일부를 가장 높은 총합을 가진 것으로 추가하려고합니다. 따라서 상위 5 개의 이름과 성 조합 만 Icecream_consumed 카운트를 갖습니다. 단지 내가 수동으로 각 레코드를 업데이트하지 않고이를 반영하기 위해 테이블에서 레코드를 수정하는 방법, 80 (5 개) 결과를하지 않은에 내가 원하는

SELECT Firstname, Lastname, SUM(Icecream_consumed) 
    FROM table_name 
GROUP BY Firstname, Lastname 
ORDER BY SUM(Icecream_consumed); 

: 예를 들어

나는 쿼리를 실행하면? 동일한 기본 키가있는 기존 레코드가있는 위치에 삽입하기 만하면 간단한 업데이트가 작동하지 않습니다.

편집 : 열 ID가 일종의 모호한 것으로 나타났습니다. 그래서이 예제에서 제거했습니다.

EDIT2는 :

기존 : 합계 (icecream_consumed되도록

이름, 성, SUM (Icecream_consumed)

John Doe 1500 
Joe Doe 1400 
Alex Foo 1111 
John Foo 1000 
Ben Foo 999 
Sue Cool 500 
Bill Smith 200 
Ben Smith 150 

I는 표를 변경하려면 다음 예는 cool, bill smith 및 ben smith와 관련된 값은 john doe와 연관되어 있으므로 5 개의 결과 만 표시됩니다. 그러나 john doe 대신 sue cool에 대한 모든 레코드를 업데이트하려고하면 같은 날짜에 icecream_consumed 값을 가질 수 있으므로 기본 키와 충돌이 발생합니다. SQL 바이올린에 예를 들어 작업

John Doe 2000 
Joe Doe 1600 
Alex Foo 1261 
John Foo 1000 
Ben Foo 999 
+0

변경하지 않고 (동일한 '기본'키를 유지하면서) 레코드를 수정하고 싶습니다. 그렇지 않다면, "현재"대 "원한"의 작은 예가 당신이 달성하고자하는 것을 더 잘 이해하는 데 도움이 될 것입니다. – alfasin

+0

'insert into x select ... from ... 중복 키 업데이트시 소비 전력 = 소비 + y'와 같은 소리가납니다. –

+0

잭은 위의 예제와 같이 당신의 답을 구술 할 수 있습니까? 나는 "중복 키"문구를 조사하고 있었고 값을 추가하는 것처럼 보이지만 동일한 총계를 유지하면서 더 작은 레코드를 없애고 아무데도 새로운 숫자를 추가하는 것이 아닙니다. –

답변

2

가 : 부속 선택이 같은 테이블 업데이트의 하나 인 경우 MySQL이 업데이트 문에서 하위 선택을 실행할 수 없습니다 http://sqlfiddle.com/#!2/0e8ab/1

때문에, 당신이 필요로하는 결과는 것처럼 보일 수 있습니다 먼저 데이터를 다른 테이블에 임시로 복사하십시오. 데이터가 아직 원자 작업이 아니므로 데이터베이스에 들어갈 때이 작업을 실행하지 마십시오. 먼저 데이터베이스를 사용하는 응용 프로그램을 종료해야합니다.

-- Create a copy of the data 
CREATE TABLE table_name_copy SELECT * FROM table_name; 

-- Update the rows with the most Icecream_consumed to have the total 
UPDATE table_name t1 SET t1.Icecream_consumed = (
    SELECT SUM(t2.Icecream_consumed) 
    FROM table_name_copy t2 
    WHERE t2.Firstname = t1.FirstName AND t2.Lastname = t1.Lastname 
) 
WHERE id = (
    SELECT id 
    FROM table_name_copy t2 
    WHERE t2.Firstname = t1.FirstName AND t2.Lastname = t1.Lastname 
    ORDER BY Icecream_consumed DESC LIMIT 1 
); 

-- Delete the other rows that don't have the new totalled Icecream_consumed 
DELETE FROM table_name 
WHERE id != (
    SELECT t2.id 
    FROM table_name_copy t2 
    WHERE t2.Firstname = table_name.FirstName AND t2.Lastname = table_name.Lastname 
    ORDER BY Icecream_consumed DESC LIMIT 1 
); 

-- Remove the copied table 
DROP TABLE table_name_copy; 
+0

이것은 내가 고려하지 않은 옵션이며 좋은 일이다. 이제는 임시 테이블을 만들지 않고 동일한 작업을 수행 할 수있는 방법이 있는지 궁금합니다. –

+0

내 머리 꼭대기에서 생각할 수있는 유일한 방법은 데이터 마이그레이션을 수행 할 작은 스크립트 또는 응용 프로그램을 작성하는 것입니다. 그러나 솔직히 말해서 그것은 아마도 더 많은 일입니다. 몇 가지 실수를 수정하고 작동하는 예를 추가했습니다. – theon

관련 문제