Bu sorunu çözmek için atılacak adımlara biraz daha uzun ve daha ayrıntılı bir açıklama ekleyeceğim. Çok uzun olursa özür dilerim.
Verdiğiniz üs ile başlayacağım ve bu yazının geri kalanı için kullanacağım birkaç terimi tanımlamak için kullanacağım. Bu temel tablo olacaktır :
select * from history;
+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
| 1 | A | 10 |
| 1 | B | 3 |
| 2 | A | 9 |
| 2 | C | 40 |
+--------+----------+-----------+
Bu bizim hedefimiz olacak, güzel pivot masa :
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
Değerler history.hostid
sütun olacak y değerleri, pivot tabloda. İçindeki değerler history.itemname
sütununda olacak x değerleri (bilinen nedenlerle).
Bir pivot tablo oluşturma sorununu çözmek zorunda kaldığımda, üç aşamalı bir işlemle (isteğe bağlı dördüncü adımla) mücadele ediyorum:
- ilgilenilen sütunları seçin, yani y-değerleri ve x-değerleri
- taban tablosunu ekstra sütunlarla genişletme - her x değeri için bir tane
- genişletilmiş tabloyu gruplama ve toplama - her y değeri için bir grup
- (isteğe bağlı) toplu tabloyu önceden onaylama
Bu adımları probleminize uygulayalım ve ne elde ettiğimize bakalım:
1.Adım: İlgilendiğiniz sütunları seçin . İstenen sonuç olarak, hostid
içerir y-değerleri ve itemname
içerir X-değerleri .
2.Adım: Temel tabloyu fazladan sütunlarla genişletin . Genellikle x-değeri başına bir sütuna ihtiyacımız vardır. X değeri sütunumuzun şunu hatırlayın 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 |
+--------+----------+-----------+------+------+------+
Satır sayısını değiştirmediğimizi unutmayın - fazladan sütun ekledik. Ayrıca, NULL
s örüntüsünün itemname = "A"
yeni sütun için null olmayan bir değere A
ve diğer yeni sütunlar için null değerine sahip bir satıra dikkat edin .
3.Adım: Genişletilmiş tabloyu gruplandırın ve toplayın . Biz gerek group by hostid
o y-değerlerini sağladığından,:
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 |
+--------+------+------+------+
(Şimdi her y değeri için bir satırımız olduğunu unutmayın.) Tamam, neredeyse geldik! Sadece bu çirkinlerden kurtulmamız gerekiyorNULL
.
4.Adım: Prettify . Null değerleri sıfırlarla değiştireceğiz, böylece sonuç kümesi bakmak daha güzel:
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 |
+--------+------+------+------+
Ve işimiz bitti - MySQL kullanarak güzel, güzel bir pivot tablo oluşturduk.
Bu prosedürü uygularken dikkat edilmesi gerekenler:
- fazladan sütunlarda kullanılacak değer. Kullandığım
itemvalue
bu örnekte
- ekstra sütunlarda ne "nötr" değeri kullanılır. Kullandım
NULL
, ama aynı zamanda 0
veya ""
tam durumunuza bağlı olarak da olabilir
- gruplama sırasında kullanılacak toplama işlevi. Kullandığım
sum
ama count
vemax
ayrıca sık (kullanılan max
birçok satırlar arasında yayılmış olmuştu tek satır "nesneleri" oluştururken sıklıkla kullanılır)
- y değerleri için birden çok sütun kullanma. Bu çözüm, y değerleri için tek bir sütun kullanmakla sınırlı değildir; yalnızca ekstra sütunları
group by
yan tümceye takın (ve select
bunları unutmayın )
Bilinen sınırlamalar:
- bu çözüm pivot tabloda n sütuna izin vermez - temel tablo genişletilirken her pivot sütununun manuel olarak eklenmesi gerekir. Yani 5 veya 10 x-değerleri için bu çözüm güzel. 100 için, çok hoş değil. Bir sorgu üreten saklı yordamlar ile bazı çözümler vardır, ancak doğru çirkin ve zor. Şu anda pivot tablonun çok sayıda sütuna sahip olması gerektiğinde bu sorunu çözmek için iyi bir yol bilmiyorum.