Tôi sẽ thêm phần giải thích dài hơn và chi tiết hơn về các bước cần thực hiện để giải quyết vấn đề này. Tôi xin lỗi nếu nó quá dài.
Tôi sẽ bắt đầu với cơ sở bạn đã đưa ra và sử dụng nó để xác định một vài thuật ngữ mà tôi sẽ sử dụng cho phần còn lại của bài đăng này. Đây sẽ là bảng cơ sở :
select * from history;
+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
| 1 | A | 10 |
| 1 | B | 3 |
| 2 | A | 9 |
| 2 | C | 40 |
+--------+----------+-----------+
Đây sẽ là mục tiêu của chúng tôi, bảng tổng hợp đẹp :
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
Các giá trị trong history.hostid
cột sẽ trở thành giá trị y trong bảng tổng hợp. Các giá trị trong history.itemname
cột sẽ trở thành giá trị x (vì những lý do rõ ràng).
Khi tôi phải giải quyết vấn đề tạo bảng tổng hợp, tôi sẽ giải quyết bằng quy trình ba bước (với bước thứ tư tùy chọn):
- chọn các cột quan tâm, tức là giá trị y và giá trị x
- mở rộng bảng cơ sở với các cột bổ sung - một cột cho mỗi giá trị x
- nhóm và tổng hợp bảng mở rộng - một nhóm cho mỗi giá trị y
- (tùy chọn) chỉnh sửa bảng tổng hợp
Hãy áp dụng các bước sau cho vấn đề của bạn và xem những gì chúng tôi nhận được:
Bước 1:chọn các cột quan tâm . Trong kết quả mong muốn, hostid
cung cấp giá trị y và itemname
cung cấp giá trị x .
Bước 2:mở rộng bảng cơ sở với các cột bổ sung . Chúng tôi thường cần một cột cho mỗi giá trị x. Nhớ lại rằng cột giá trị x của chúng ta là itemname
:
create view history_extended as (
select
history.*,
case when itemname = "A" then itemvalue end as A,
case when itemname = "B" then itemvalue end as B,
case when itemname = "C" then itemvalue end as C
from history
);
select * from history_extended;
+--------+----------+-----------+------+------+------+
| hostid | itemname | itemvalue | A | B | C |
+--------+----------+-----------+------+------+------+
| 1 | A | 10 | 10 | NULL | NULL |
| 1 | B | 3 | NULL | 3 | NULL |
| 2 | A | 9 | 9 | NULL | NULL |
| 2 | C | 40 | NULL | NULL | 40 |
+--------+----------+-----------+------+------+------+
Lưu ý rằng chúng tôi không thay đổi số hàng - chúng tôi chỉ thêm các cột bổ sung. Cũng lưu ý mẫu của NULL
s - một hàng có itemname = "A"
có giá trị khác rỗng cho cột mới A
và giá trị null cho các cột mới khác.
Bước 3:nhóm và tổng hợp bảng mở rộng . Chúng ta cần group by hostid
, vì nó cung cấp các giá trị y:
create view history_itemvalue_pivot as (
select
hostid,
sum(A) as A,
sum(B) as B,
sum(C) as C
from history_extended
group by hostid
);
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | NULL |
| 2 | 9 | NULL | 40 |
+--------+------+------+------+
(Lưu ý rằng chúng tôi hiện có một hàng cho mỗi giá trị y.) Được rồi, chúng ta sắp hoàn tất! Chúng ta chỉ cần loại bỏ những NULL
xấu xí đó s.
Bước 4:kiểm tra trước . Chúng tôi sẽ thay thế bất kỳ giá trị null nào bằng các số 0 để tập hợp kết quả trông đẹp hơn:
create view history_itemvalue_pivot_pretty as (
select
hostid,
coalesce(A, 0) as A,
coalesce(B, 0) as B,
coalesce(C, 0) as C
from history_itemvalue_pivot
);
select * from history_itemvalue_pivot_pretty;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
Và chúng tôi đã hoàn thành - chúng tôi đã xây dựng một bảng tổng hợp đẹp mắt bằng cách sử dụng MySQL.
Những lưu ý khi áp dụng quy trình này:
- giá trị nào để sử dụng trong các cột bổ sung. Tôi đã sử dụng
itemvalue
trong ví dụ này - giá trị "trung tính" nào để sử dụng trong các cột bổ sung. Tôi đã sử dụng
NULL
, nhưng nó cũng có thể là0
hoặc""
, tùy thuộc vào tình huống chính xác của bạn - hàm tổng hợp nào sẽ sử dụng khi nhóm. Tôi đã sử dụng
sum
, nhưngcount
vàmax
cũng thường được sử dụng (max
thường được sử dụng khi xây dựng "đối tượng" một hàng được trải rộng trên nhiều hàng) - sử dụng nhiều cột cho các giá trị y. Giải pháp này không giới hạn ở việc sử dụng một cột duy nhất cho các giá trị y - chỉ cần cắm các cột bổ sung vào nhóm
group by
mệnh đề (và đừng quênselect
họ)
Các hạn chế đã biết:
- giải pháp này không cho phép n cột trong bảng tổng hợp - mỗi cột tổng hợp cần được thêm theo cách thủ công khi mở rộng bảng cơ sở. Vì vậy, đối với 5 hoặc 10 giá trị x, giải pháp này là tốt. Đối với 100, không phải là tốt đẹp. Có một số giải pháp với các thủ tục được lưu trữ tạo ra một truy vấn, nhưng chúng xấu và khó làm đúng. Tôi hiện không biết cách hay để giải quyết vấn đề này khi bảng tổng hợp cần có nhiều cột.