1

次のような 2 つのテーブルがあります。

人:

id | name | sale | commission
1  | abc  | 0    |   0
2  | xyz  | 0    |   0

セール:

id | date       | person_id | sale | commission
1  | 2016-05-01 |     1     | 10   |     1
2  | 2016-05-02 |     1     | 10   |     1
3  | 2016-05-03 |     1     | 10   |     1
4  | 2016-05-01 |     2     | 20   |     2
5  | 2016-05-02 |     2     | 20   |     2
6  | 2016-05-01 |     2     | 20   |     2

単一の更新クエリで person テーブルを更新し、テーブルを次のように変更したい:

人:

id | name | sale | commission
1  | abc  | 30   |   3
2  | xyz  | 60   |   6

次のように売上を合計できることはわかっていますが、次のクエリ結果を個人テーブルに直接更新する方法は知っています。

SELECT person_id, SUM(sale), SUM(commission) 
FROM sale
GROUP BY person_id; 
4

2 に答える 2

2

あなたの質問の下のコメントでストロベリーが言ったように、この情報を保存する前によく考えてください。非正規化され、古くなります。むしろ、レポート生成時に使用することを検討してください。そうしないと、前述のように、問題が発生する可能性があります。

drop table if exists person;
create table person
(   personId int auto_increment primary key,
    name varchar(100) not null,
    totSales decimal(9,2) not null,
    totComm decimal(9,2)
);
insert person(name,totSales,totComm) values
('Joe',0,0),
('Sally',0,0);
-- just added persons 1 and 2 (auto_inc)

drop table if exists sale;
create table sale
(   saleId int auto_increment primary key,
    saleDate date not null,
    personId int not null,
    sale decimal(9,2) not null,
    commission decimal(9,2) not null,
    index(personId), -- facilitate a snappier "group by" later
    foreign key (personId) references person(personId) -- Ref Integrity
);

insert sale(saleDate,personId,sale,commission) values
('2016-05-01',2,10,1),
('2016-05-01',1,40,4),
('2016-05-02',1,30,3),
('2016-05-07',2,10,1),
('2016-05-07',2,90,9);

-- the following dies on referential integrity, FK, error 1452 as expected
insert sale(saleDate,personId,sale,commission) values ('2016-05-01',4,10,1);

更新ステートメント

update person p 
join  
(   select personId,sum(sale) totSales, sum(commission) totComm 
    from sale 
    group by personId 
) xDerived 
on xDerived.personId=p.personId 
set p.totSales=xDerived.totSales,p.totComm=xDerived.totComm;

結果

select * from person;
+----------+-------+----------+---------+
| personId | name  | totSales | totComm |
+----------+-------+----------+---------+
|        1 | Joe   |    70.00 |    7.00 |
|        2 | Sally |   110.00 |   11.00 |
+----------+-------+----------+---------+
2 rows in set (0.00 sec)

xDerived単なる別名です。エイリアス名を明示的に使用するかどうかに関係なく、すべての派生テーブルにはエイリアス名が必要です。

于 2016-06-01T16:50:11.090 に答える
1
 UPDATE person
 SET sale = (
    SELECT SUM(s.sale) FROM sale s
    WHERE s.person_id = person.id
 );

私のために働きます。http://ideone.com/F32oUUで動作を確認してください。

追加の集計列を含む新しいバージョンの編集:

UPDATE person SET 
 sale = (
    SELECT SUM(s.sale) FROM sale s
    WHERE s.person_id = person.id
 ),
 commission = (
    SELECT SUM(s.commission) FROM sale s
    WHERE s.person_id = person.id
 );

http://ideone.com/yo1A9Y

そうは言っても、JOINソリューションの方が優れていると確信しており、別の回答者がそのようなソリューションを投稿できることを願っています。

于 2016-06-01T16:02:21.640 に答える