简体   繁体   English

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

[英]mysql query to dynamically convert row data to columns

I am working on a pivot table query. 我正在进行数据透视表查询。 The schema is as follows 架构如下

Sno, Name, District Sno,名称,区

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). 如你所见,我有一组4个不同的区域(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. 我这样问,因为查询的输出“ 从district_details中选择不同(区) ”将返回一个在每一行都有区名的单列,我希望将其转换为列。

You simply cannot have a static SQL statement returning a variable number of columns. 您根本无法使用返回可变数量列的静态SQL语句。 You need to build such statement each time the number of different districts changes. 每当不同地区的数量发生变化时,您需要建立此类声明。 To do that, you execute first a 要做到这一点,首先执行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) 然后构建一个迭代前一个结果的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;"

And execute that query. 并执行该查询。 You'll then need have to handle in your code the processing of the variable number of columns 然后,您需要在代码中处理可变数量的列的处理

a) "For each " is not supported in MySQL stored procedures. a)MySQL存储过程不支持“for each”。 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. b)存储过程不能使用所谓的动态SQL语句从连接字符串中执行预准备语句,也不能返回具有多个不同行的结果。 c) Stored functions cannot execute dynamic SQL at all. c)存储的函数根本不能执行动态SQL。

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 1)创建临时表2)使用if语句从列向临时表加载数据3)将临时表加载到存储过程中的INOUT或OUT参数,就像调用表一样...如果可以让它返回不止一排

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; 从@yourqyerstring准备stmName; execute stmName; 执行stmName; deallocate prepare stmName; deallocate准备stmName;

(find much more on the stored procedures part of the mysql forum too) (在mysql论坛的存储过程部分找到更多)

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 我在表格中处理纯文本内容,没有任何可以求和,计算或加起来的内容

The following assumes you want matches of distinct (name/district) pairs. 以下假设您需要不同(名称/地区)对的匹配。 Ie Luke/CA and Duke/CA would yield two results: 即Luke / CA和Duke / CA将产生两个结果:

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. 如果不是这种情况,只需从GROUP BY子句中删除name即可。

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. 最后,请注意我在count()中切换sum() ,因为您试图计算所有分组的行而不是获取值的总和。

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

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: 使用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! 魔法!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM