mysql查询将行数据动态转换为列

时间:2009-10-21 09:51:50

标签: sql mysql pivot-table

我正在进行数据透视表查询。 架构如下

Sno,姓名,区

许多地区可能出现相同的名称,例如以样本数据为例

1 Mike CA
2 Mike CA
3 Proctor JB
4 Luke MN
5 Luke MN
6 Mike CA
7 Mike LP
8 Proctor MN
9 Proctor JB
10 Proctor MN
11 Luke MN

如你所见,我有一组4个不同的区域(CA,JB,MN,LP)。现在,我希望通过将名称映射到区域

来获取为其生成的数据透视表
Name CA JB MN LP
Mike 3 0 0 1
Proctor 0 2 2 0
Luke 0 0 3 0

我为此写了以下查询

select name,sum(if(District="CA",1,0)) as "CA",sum(if(District="JB",1,0)) as "JB",sum(if(District="MN",1,0)) as "MN",sum(if(District="LP",1,0)) as "LP" from district_details group by name

然而,区域可能会增加,在这种情况下,我将不得不再次手动编辑查询并添加新区域。

我想知道是否有一个查询可以动态获取不同区域的名称并运行上述查询。我知道我可以通过一个程序来实现并动态生成脚本,还有其他任何方法吗?

我这样问,因为查询“从district_details选择不同(区)”的输出将返回一行,每行都有一个区名,我希望将其转换为列。

4 个答案:

答案 0 :(得分:3)

您根本无法使用返回可变数量列的静态SQL语句。每当不同地区的数量发生变化时,您需要建立此类声明。要做到这一点,首先执行

SELECT DISTINCT District FROM district_details;

这将为您提供有详细信息的地区列表。然后构建一个迭代前一个结果(伪代码)的SQL语句

statement = "SELECT name "

For each row returned in d = SELECT DISTINCT District FROM district_details 
    statement = statement & ", SUM(IF(District=""" & d.District & """,1 ,0)) AS """ & d.District & """" 

statement = statement & " FROM district_details GROUP BY name;"

执行该查询。然后,您需要在代码中处理可变数量列的处理

答案 1 :(得分:1)

a)MySQL存储过程不支持“for each”。 b)存储过程不能使用所谓的动态SQL语句从连接字符串中执行预准备语句,也不能返回具有多个不同行的结果。 c)存储的函数根本无法执行动态SQL。

一旦你有了一个好主意就跟踪一个噩梦,每个人在他们想到“为什么有人想要......”之前似乎要揭穿它。

我希望你找到你的解决方案,我仍在寻找我的解决方案。 我收到的关闭是

(原谅伪代码)

- >到存储过程,构建函数...

1)创建临时表 2)使用if语句从列中将数据加载到临时表 3)将临时表加载到存储过程中的INOUT或OUT参数,就像调用表一样...如果可以让它返回多行

另一个提示...... 将您的区域存储为表格常规样式,加载此区域并通过循环标记为活动的区域进行迭代,以动态连接可以是所有系统关注的纯文本的查询字符串

然后使用;

从@yourqyerstring准备stmName;  执行stmName;  deallocate准备stmName;

(在mysql论坛的存储过程部分找到更多内容)

每次都要运行一组不同的区域,而不必重新设计原始的proc

也许数字形式更容易。 我在我的表格中处理纯文本内容,无需总结,计算或加起来

答案 2 :(得分:0)

以下假设您需要不同(名称/地区)对的匹配。即Luke / CA和Duke / CA将产生两个结果:

SELECT name, District, count(District) AS count
FROM district_details
GROUP BY District, name

如果不是这种情况,只需从GROUP BY子句中删除名称。

最后,请注意我为 count()切换 sum(),因为您尝试计算所有分组的行而不是获取值的总和。 / p>

答案 3 :(得分:0)

通过@cballou上面的评论,我能够执行这种功能,这不是OP所要求的,但适合我的类似情况,所以在这里添加它以帮助那些追随者。

正常选择语句:

SELECT d.id ID,
       q.field field,
       q.quota quota
  FROM defaults d
  JOIN quotas q ON d.id=q.default_id

垂直结果:

ID field  quota
1  male   25
1  female 25
2  male   50

使用group_concat选择语句:

SELECT d.id ID,
       GROUP_CONCAT(q.fields SEPARATOR ",") fields,
       GROUP_CONCAT(q.quotas SEPARATOR ",") quotas
  FROM defaults d
  JOIN quotas q ON d.id=q.default_id

然后我得到逗号分隔的“字段”和“配额”字段,然后我可以稍后以编程方式轻松处理。

横向结果:

ID fields      quotas
1  male,female 25,25
2  male        50

魔术!