31

我在长/高格式的 mysql 表中有数据(如下所述),并希望将其转换为宽格式。我可以只使用 sql 来做到这一点吗?

举个例子最容易解释。假设您有 M 个国家的(国家、密钥、价值)信息,N 个密钥(例如,密钥可以是收入、政治领袖、地区、大陆等)

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'

SQL中有没有办法用宽格式的数据创建一个新表?

select distinct key from table;

// 这会给我所有的钥匙。

1)然后如何使用这些关键元素创建表格?

2)然后我如何填写表格值?

我很确定我可以使用任何脚本语言(我喜欢 python)来做到这一点,但想知道在 mysql 中是否有一种简单的方法可以做到这一点。许多统计软件包(如 R 和 STATA)都内置了这个命令,因为它经常被使用。

======

更清楚地说,这是一个简单案例所需的输入输出:

输入:

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

输出

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

3 回答 3

31

交叉表或数据透视表就是答案。从那里您可以选择 FROM ... INSERT INTO ... 或从单个 SELECT 创建一个视图。

就像是:

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

FROM table 
GROUP BY country;

欲了解更多信息:http ://dev.mysql.com/tech-resources/articles/wizard/index.html

于 2010-02-24T23:46:46.600 回答
6

我想我找到了解决方案,它使用 VIEWS 和 INSERT INTO(如 e4c5 所建议的那样)。

您必须自己获取 AttrNames/Keys 列表,但 MYSQL 会完成其他繁重的工作。

对于上面的简单测试用例,使用适当的列创建 new_table(不要忘记还有一个自动递增的主键)。然后

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;

如果您有更多 attrNames,则为每个视图创建一个视图,然后相应地调整最后一条语句。

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;

还有一些提示

  • 使用 NATURAL LEFT JOIN 并且您不必指定 ON 子句
于 2010-02-24T23:29:57.623 回答
5

如果您使用的是 SQL Server,那么使用UNPIVOT会很容易。据我所知,这并没有在 MySQL 中实现,所以如果你想这样做(我建议不要这样做),你可能必须动态生成 SQL,这很麻烦。

于 2010-02-12T22:52:55.560 回答