4

我正在处理数据透视表查询。架构如下

斯诺,名称,地区

同名可能出现在多个地区,例如以样本数据为例

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

但是,地区可能会增加,在这种情况下,我将不得不再次手动编辑查询并将新地区添加到其中。

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

我之所以这么问,是因为查询“ select distinct(districts) from district_details ”的输出将返回我在每一行上都有区名称的单列,我希望将其转置到该列。

4

4 回答 4

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;"

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

于 2009-10-22T18:31:55.527 回答
1

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

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

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

(请原谅伪代码)

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

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

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

然后使用;

从@yourqyerstring 准备stmName;执行stmName;解除分配准备stmName;

(也可以在 mysql 论坛的存储过程部分找到更多信息)

每次运行一组不同的区域,而无需重新设计您的原始过程

也许以数字形式更容易。我在我的表格中处理纯文本内容,没有任何东西可以求和、计数或相加

于 2010-03-29T22:56:30.687 回答
0

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

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

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

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

于 2009-10-21T10:28:46.473 回答
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

魔法!

于 2011-09-30T20:27:35.917 回答