Tôi sẽ thêm một lời 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 xoay vòng đẹ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 trụ. Các giá trị trong history.itemname
cột sẽ trở thành giá trị x (vì lý do rõ ràng).
Khi tôi phải giải quyết vấn đề tạo bảng xoay vòng, tôi giải quyết nó 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à x-giá trị
- 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) sắp xếp lại bảng tổng hợp
Hãy áp dụng các bước này 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 các giá trị y và itemname
cung cấp các giá trị x .
Bước 2: mở rộng bảng cơ sở với các cột phụ . Chúng tôi thường cần một cột cho mỗi giá trị x. Hãy nhớ rằng cột giá trị x của chúng tôi 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ố lượng 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 itemname = "A"
có giá trị khác null 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 tôi sắp hoàn thành! Chúng ta chỉ cần thoát khỏi những NULL
s xấu xí .
Bước 4: tô điểm . Chúng ta sẽ thay thế bất kỳ giá trị null nào bằng số 0 để tập kết quả đẹp hơn để xem xét:
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 trụ đẹp, đẹp bằng cách sử dụng MySQL.
Cân nhắc khi áp dụng thủ tục này:
- giá trị nào để sử dụng trong các cột thêm. Tôi đã sử dụng
itemvalue
trong ví dụ này
- giá trị "trung tính" nào sẽ được sử dụng trong các cột thêm. Tôi đã sử dụng
NULL
, nhưng nó cũng có thể 0
hoặc ""
, tùy thuộc vào tình huống chính xác của bạn
- chức năng tổng hợp nào để sử dụng khi nhóm. Tôi đã sử dụng
sum
, nhưng count
và max
cũng thường được sử dụng ( max
thường được sử dụng khi xây dựng các "đố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 giá trị y. Giải pháp này không giới hạn trong 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
group by
mệnh đề (và đừng quên select
chúng)
Những hạn chế đã biết:
- giải pháp này không cho phép n cột trong bảng trụ - mỗi cột cần phải được thêm 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 đẹp. Đối với 100, không 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ấy đúng. Hiện tại tôi không biết một cách hay để giải quyết vấn đề này khi bảng trụ cần có nhiều cột.