【发布时间】:2022-01-16 01:33:51
【问题描述】:
我需要编写一个 MySQL 查询,它单独返回每列模式的出现次数,而不显式指定列名。
假设数据是:
| apples | bananas | oranges |
| 4 | 4 | 3 |
| 2 | 2 | 1 |
| 4 | 3 | 5 |
| 3 | 3 | 5 |
| 4 | 1 | 5 |
我要找的结果是:
| mode | count |
| 4 | 3 |
| 3 | 2 |
| 5 | 3 |
获取单个列的模式(苹果):
SELECT apples AS mode, COUNT(*) AS Count
FROM tablename
GROUP BY apples
HAVING COUNT(*) >= ALL (SELECT COUNT(*) FROM tablename GROUP BY apples);
要返回列名,我可以执行以下操作:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tablename'
效率低下且使用明确的列名,我可以使用 UNION 实现结果:
SELECT apples AS mode, COUNT(*) AS Count
FROM tablename
GROUP BY apples
HAVING COUNT(*) >= ALL (SELECT COUNT(*) FROM tablename GROUP BY apples)
UNION
SELECT bananas AS mode, COUNT(*) AS Count
FROM tablename
GROUP BY bananas
HAVING COUNT(*) >= ALL (SELECT COUNT(*) FROM tablename GROUP BY bananas)
UNION
SELECT oranges AS mode, COUNT(*) AS Count
FROM tablename
GROUP BY oranges
HAVING COUNT(*) >= ALL (SELECT COUNT(*) FROM tablename GROUP BY oranges)
我一直在尝试将这两者与 GROUP BY 和子查询结合起来的一堆不同的查询,但它们一团糟,而且我没有取得太大进展。我还没有生成一个查询来有效地显示每列的模式并明确指定列名(更不用说使用第二个查询返回的列名了)。
例如(我什至不觉得我在正确的轨道上):
SELECT COUNT(*) AS count
FROM tablename
GROUP BY (
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tablename')
HAVING COUNT(*) >= ALL (SELECT COUNT(*) FROM tablename
GROUP BY (
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tablename'))
谢谢!!
【问题讨论】:
-
您不能在查询中动态设置列名或表名。您需要动态生成sql查询文本然后执行。
-
你知道列数吗?你的mysql版本是多少?
-
@ProGu 它必须是动态的,因此可以将相同的查询应用于具有任意列数的任何表。版本是 8.0
-
从 information_schema 中选择
COLUMN_NAME返回一个 字符串,而不是一个标识符。 @Shadow 是正确的,在 SQL 中,所有语法和标识符都必须在解析查询时固定。无法进行查询以在执行期间动态更改它引用的列。您必须分两步执行此操作:一是格式化查询,然后执行该查询。 -
我尝试了很长时间才想出一些 hacky 方法来做到这一点,但结果却一无所获。如果我处于你的位置,我会编写一个小程序,发送一个查询以获取表名列表,然后遍历结果并为每一列发送一个额外的查询。所以结果将是一个包含 N 列的表,您以编程方式运行 N+1 个查询。我知道这不是您想要做的,但我认为根据您的要求,这是最好的方式。