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

发布于 2024-08-08 05:42:04 字数 857 浏览 3 评论 0原文

我正在研究数据透视表查询。 架构如下

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中选择不同的(地区)”强>”将返回一个单列,每行都有地区名称,我希望将其转置到该列。

I am working on a pivot table query.
The schema is as follows

Sno, Name, District

The same name may appear in many districts eg take the sample data for example

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

As you see i have a set of 4 distinct districts (CA, JB, MN, LP). Now i wanted to get the pivot table generated for it by mapping the name against districts

Name CA JB MN LP
Mike 3 0 0 1
Proctor 0 2 2 0
Luke 0 0 3 0

i wrote the following query for this

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

However there is a possibility that the districts may increase, in that case i will have to manually edit the query again and add the new district to it.

I want to know if there is a query which can dynamically take the names of distinct districts and run the above query. I know i can do it with a procedure and generating the script on the fly, is there any other method too?

I ask so because the output of the query "select distinct(districts) from district_details" will return me a single column having district name on each row, which i will like to be transposed to the column.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

忘东忘西忘不掉你 2024-08-15 05:42:04

您根本无法让静态 SQL 语句返回可变数量的列。每次不同地区的数量发生变化时,您都需要构建这样的语句。为此,您首先执行 a

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

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

You simply cannot have a static SQL statement returning a variable number of columns. You need to build such statement each time the number of different districts changes. To do that, you execute first a

SELECT DISTINCT District FROM district_details;

This will give you the list of districts where there are details. You then build a SQL statement iterating over the previous result (pseudocode)

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

And execute that query. You'll then need have to handle in your code the processing of the variable number of columns

木槿暧夏七纪年 2024-08-15 05:42:04

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

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

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

(请原谅伪代码)

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

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

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

然后使用;

从 @yourqyerstring 准备 stmName;
执行stmName;
释放准备stmName;

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

每次运行一组不同的分区,而不必重新设计原始过程

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

a) "For each " is not supported in MySQL stored procedures.
b) Stored procedures cannot execute prepared statements from concatenated strings using so called dynamic SQL statements, nor can it return results with more than One distinct row.
c) Stored functions cannot execute dynamic SQL at all.

It is a nightmare to keep track of once you got a good idea and everyone seems to debunk it before they think "Why would anyone wanna..."

I hope you find your solution, I am still searching for mine.
The closes I got was

(excuse the pseudo code)

-> to stored procedure, build function that...

1) create temp table
2) load data to temp table from columns using your if statements
3) load the temp table out to INOUT or OUT parameters in a stored procedure as you would a table call... IF you can get it to return more than one row

Also another tip...
Store your districts as a table conventional style, load this and iterate by looping through the districts marked active to dynamically concatenate out a querystring that could be plain text for all the system cares

Then use;

prepare stmName from @yourqyerstring;
execute stmName;
deallocate prepare stmName;

(find much more on the stored procedures part of the mysql forum too)

to run a different set of districts every time, without having to re-design your original proc

Maybe it's easier in numerical form.
I work on plain text content in my tables and have nothing to sum, count or add up

鹿童谣 2024-08-15 05:42:04

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

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

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

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

The following assumes you want matches of distinct (name/district) pairs. I.e. Luke/CA and Duke/CA would yield two results:

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

If this is not the case simply remove name from the GROUP BY clause.

Lastly, notice that I switched sum() for count() as you are trying to count all of the grouped rows rather than getting a summation of values.

夢归不見 2024-08-15 05:42:04

通过上面@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

神奇!

Via comment by @cballou above, I was able to perform this sort of function which is not exactly what OP asked for but suited my similar situation, so adding it here to help those who come after.

Normal select statement:

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

Vertical results:

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

Select statement using 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

Then I get comma-separated fields of "fields" and "quotas" which I can then easily process programmatically later.

Horizontal results:

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

Magic!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文