2010-02-12 24 views
16

Tôi có dữ liệu trong bảng mysql ở định dạng dài/cao (được mô tả bên dưới) và muốn chuyển đổi sang định dạng rộng. Tôi có thể làm điều này bằng cách sử dụng chỉ sql?Mysql, định hình lại dữ liệu từ dài/cao đến rộng

Dễ nhất để giải thích bằng ví dụ. Giả sử bạn có thông tin về (quốc gia, trọng điểm, giá trị) cho các nước M, phím N (ví dụ như các phím có thể thu nhập, lãnh đạo chính trị, khu vực, châu lục, vv)

Long format has 3 columns: country, key, value 
    - M*N rows. 
    e.g. 
    'USA', 'President', 'Obama' 
    ... 
    'USA', 'Currency', 'Dollar' 

Wide format has N=16 columns: county, key1, ..., keyN 
    - M rows 
example: 
    country, President, ... , Currency 
    'USA', 'Obama', ... , 'Dollar' 

Có cách nào trong SQL để tạo một bảng mới với dữ liệu ở định dạng rộng?

select distinct key from table; 

// điều này sẽ cho tôi tất cả các khóa.

1) Làm cách nào để tạo bảng bằng các yếu tố chính này?

2) Làm cách nào để điền các giá trị bảng?

Tôi khá chắc chắn rằng tôi có thể làm điều này với bất kỳ ngôn ngữ kịch bản nào (tôi thích python), nhưng muốn biết nếu có một cách dễ dàng để làm điều này trong mysql. Nhiều gói thống kê như R và STATA có lệnh này được xây dựng bởi vì nó thường được sử dụng.

======

Để được rõ ràng hơn, đây là sản phẩm đầu vào mong muốn cho một trường hợp đơn giản:

Input:

country attrName attrValue  key (these are column names) 
US   President Obama   2 
US   Currency Dollar  3 
China  President Hu   4 
China  Currency Yuan   5 

Output

country President Currency newPkey 
US   Obama  Dollar  1 
China  Hu   Yuan  2 

Trả lời

11

Cross-tab hoặc trục bảng là câu trả lời. Từ đó bạn có thể SELECT FROM ... INSERT INTO ... hoặc tạo VIEW từ một SELECT duy nhất.

Cái gì như:

SELECT country, 
     MAX(IF(key='President', value, NULL)) AS President, 
     MAX(IF(key='Currency', value, NULL)) AS Currency, 
     ... 

FROM table 
GROUP BY country; 

Để biết thêm thông: http://dev.mysql.com/tech-resources/articles/wizard/index.html

+3

cách tôi làm việc. Cách của bạn tốt hơn nhiều. Tôi yêu bạn hoặc cảm ơn. Hãy lựa chọn bạn thích cái nào để thể hiện sự đánh giá cao. – chongman

+1

Toán tử IF là độc quyền đối với MySQL. Sử dụng CASE thay vì tuân thủ với SQL chuẩn. Chi tiết hơn ở đây: [SQLite dài đến các định dạng rộng?] (Http://www.stackoverflow.com/questions/2444708/sqlite-long-to-wide-formats) – SuperAce99

+0

@mluebke: liên kết của bạn đã chết: ( –

3

Nếu bạn đang sử dụng SQL Server, điều này sẽ dễ dàng sử dụng UNPIVOT. Theo tôi biết, điều này không được thực hiện trong MySQL, vì vậy nếu bạn muốn làm điều này (và tôi khuyên bạn nên chống lại nó) bạn có thể sẽ phải tạo SQL động, và đó là lộn xộn.

3

Tôi nghĩ rằng tôi đã tìm thấy giải pháp, sử dụng VIEWS và INSERT INTO (theo đề xuất của e4c5).

Bạn phải tự mình nhận danh sách AttrNames/Keys, nhưng MYSQL thực hiện việc nâng hạng nặng khác.

Đối với trường hợp thử nghiệm đơn giản ở trên, hãy tạo new_table với các cột thích hợp (cũng đừng quên có khóa chính tăng tự động). Sau đó,

CREATE VIEW a 
AS SELECT country, attrValue 
WHERE attrName="President"; 

CREATE VIEW b 
AS SELECT country, attrValue 
WHERE attrName="Currency"; 


INSERT INTO newtable(country, President, Currency) 
SELECT a.country, a.attrValue, b.attrValue 
FROM a 
INNER JOIN b ON a.country=b.country; 

Nếu bạn có thêm attrNames, thì hãy tạo một chế độ xem cho mỗi cái và sau đó điều chỉnh câu lệnh cuối cùng cho phù hợp.

INSERT INTO newtable(country, President, Currency, Capital, Population) 
SELECT a.country, a.attrValue, b.attrValue, c.attrValue, d.attrValue 
FROM a 
INNER JOIN b ON a.country=b.country 
INNER JOIN c ON a.country=c.country 
INNER JOIN d ON a.country=d.country; 

Một số lời khuyên hơn

  • sử dụng TỰ NHIÊN LEFT JOIN và bạn không cần phải chỉ định mệnh đề ON
Các vấn đề liên quan