我有一个包含n列和x行的表。
我想进行查询以显示包含所有列的表以及该列的最大长度值(以及具有最大值长度的该行的行ID)。
+--------+--------+----+
| column | length | id |
+--------+--------+----+
| a | 123 | 1 |
| b | 123 | 8 |
| c | 123 | 6 |
| d | 123 | 5 |
| e | 123 | 3 |
+--------+--------+----+
a,b,c等是列名,长度是该列中的最大长度,id是该列的最大值长度的行。
这样的东西?但随后动态地为所有列:
SELECT MAX(LENGTH(`column_a`)) AS `length`, `id`
FROM `table` GROUP BY LENGTH(`column_a`)
ORDER BY LENGTH(`column_a`) DESC LIMIT 1
就像添加了两列的下一个查询(最大长度和行ID)
SHOW COLUMNS FROM `table`
也许还使用此查询来获取特定表的列名:
SELECT `column_name` AS `column`
FROM `information_schema`.`columns`
WHERE `table_name` = 'table'
AND `column_name` != 'id'
ORDER BY `ordinal_position`
几乎就在那里(感谢Bill)......(只需指定'table')但现在如何运行_SQL al同样的运行......
SELECT CONCAT(GROUP_CONCAT(CONCAT('(SELECT \'', `column_name`,'\' AS `column`, LENGTH(`', `column_name`,'`) AS `length`, id ', 'FROM `', `table_schema`,'`.`', `table_name`,'` ORDER BY `length` DESC LIMIT 1)') SEPARATOR ' UNION ALL '), ';') AS _SQL
FROM `information_schema`.`columns`
WHERE `table_name` = 'table'
AND `column_name` IN (
SELECT `column_name`
FROM `information_schema`.`columns`
WHERE `table_name` = 'table'
AND `column_name` != 'id'
ORDER BY `ordinal_position`);
答案 0 :(得分:4)
MySQL没有任何方法可以在单个查询中执行您想要的操作。在准备查询时,必须修复对列的所有引用。
您可以做的最好的事情是对INFORMATION_SCHEMA使用一个查询来生成一个新的动态SQL查询,以获取您想要的信息。
我针对MySQL 5.5.16进行了测试:
SELECT CONCAT(GROUP_CONCAT(
CONCAT('(SELECT \'',COLUMN_NAME,'\' AS `column`, LENGTH(`',COLUMN_NAME,'`) AS `length`, id ',
'FROM `',TABLE_SCHEMA,'`.`',TABLE_NAME,'` ORDER BY `length` DESC LIMIT 1)')
SEPARATOR ' UNION ALL '), ';') AS _SQL
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (TABLE_SCHEMA, TABLE_NAME) = ('test', 'tt')
AND COLUMN_NAME IN ('a', 'b', 'c');
此查询产生以下输出(为了在此处发布,我添加了换行符):
(SELECT 'a' AS `column`, LENGTH(`a`) AS `length`, id
FROM `test`.`tt` ORDER BY `length` DESC LIMIT 1)
UNION ALL
(SELECT 'b' AS `column`, LENGTH(`b`) AS `length`, id
FROM `test`.`tt` ORDER BY `length` DESC LIMIT 1)
UNION ALL
(SELECT 'c' AS `column`, LENGTH(`c`) AS `length`, id
FROM `test`.`tt` ORDER BY `length` DESC LIMIT 1);
生成的查询在我的测试中返回以下结果:
+--------+--------+----+
| column | length | id |
+--------+--------+----+
| a | 10 | 2 |
| b | 9 | 1 |
| c | 6 | 2 |
+--------+--------+----+
请注意,这不会解决关系。如果多个行具有相同的最长字符串,则它将仅报告一个id
,任意选择。
重新提出你的额外问题:
您必须将它们作为两个单独的查询来执行。我在回答的开头说过,在准备查询时必须在SQL字符串中修复列引用。您无法动态发现列,也无法在同一查询中查询其数据。
重新评论:
GROUP_CONCAT()返回的最长字符串默认为1024,这足以为9列生成此SQL查询。您可以增加此限制:
SET group_concat_max_len = 1024*1024;
这仅增加当前数据库会话的限制。您可以使用SET GLOBAL ...
为所有会话更改它。如果您希望在重新启动MySQL后保持此值,请在my.cnf文件中设置该值(无需在配置文件中使用SET GLOBAL
)。
答案 1 :(得分:1)
解决这个问题会有点棘手,所以我不打算编写确切的SQL,但这里有一般的想法:
创建一个表变量来保存结果。它将具有您在答案中发布的相同架构。
创建另一个表变量以保存要转动的所有列名。您只需要一个带有名称列的表。
将列名插入到步骤2中创建的临时表中:
插入@TempTable(ColumnName) 从information_schema.columns中选择COLUMN_NAME,其中Table_Name ='YourTable';
使用游标循环遍历列名表变量中的每一列。
在循环中,您将使用PREPARE STATEMENT函数创建并执行动态SQL查询。通过循环的每次迭代都会在结果表中为一个列名插入一行。
从@query预备STMT; 执行STMT;
这是对需要执行的动态SQL的准备。 @columnName是循环中变量的名称。
declare @maxLength int;
select @maxLength = max(length(@ColumnName)) maxlength from YourTable;
insert into @results (ColumnName, MaxLength, RowId)
select '@ColumnName', @maxLength, Id from YourTable where length(@ColumnName)) = @maxLength;
或者,您可以将数据转储到Excel中并使用数据透视表功能:)
答案 2 :(得分:0)
试试这个:
SELECT
length(concat('',a)) as maxlen,
group_concat(if (length(concat('',a))=@maxlen_a,a,null)) as maxlenval
FROM
(select @maxlen_a:=max(length(concat('',a))) from tablename) as aview,
tablename
GROUP BY maxlen
HAVING maxlenval IS NOT null
UNION
SELECT
length(concat('',b)) as maxlen,
group_concat(if (length(concat('',b))=@maxlen_b,b,null)) as maxlenval
FROM
(select @maxlen_b:=max(length(concat('',b))) from tablename) as bview,
tablename
GROUP BY maxlen
HAVING maxlenval IS NOT null
......等等每一栏。
这也解决了两个相同长度的不同值的问题
答案 3 :(得分:0)
如果我理解你需要的东西,这样的东西应该有效(在Mysql 5.1上测试):
SELECT
column, length, id
FROM
(
(SELECT 'a' AS column, CHAR_LENGTH(a) AS length, id
FROM yourtable
ORDER BY length DESC
LIMIT 1)
UNION
(SELECT 'b' AS column, CHAR_LENGTH(b) AS length, id
FROM yourtable
ORDER BY length DESC
LIMIT 1)
UNION
(SELECT 'c' AS column, CHAR_LENGTH(c) AS length, id
FROM yourtable
ORDER BY length DESC
LIMIT 1)
UNION
(...)
) T