【问题标题】:MySQL Get Total Query from Unknown Columns at RuntimeMySQL 在运行时从未知列获取总查询
【发布时间】:2020-07-31 08:59:36
【问题描述】:

我试图在运行时从表中获取未知列的总数。

这是 source_table:

+----+------------+-----------+-----------+-----------+-----------+-----------+
| ID | Name       | Unknown 1 | Unknown 2 | Unknown 3 | Unknown 4 | Unknown 5 |
+----+------------+-----------+-----------+-----------+-----------+-----------+
| 1  | abc        |     10.00 |     18.00 |      5.00 |     21.00 |      6.00 |
+----+------------+-----------+-----------+-----------+-----------+-----------+
| 2  | ghq        |     22.00 |     14.00 |     12.00 |     11.00 |     23.00 |
+----+------------+-----------+-----------+-----------+-----------+-----------+
| 3  | xyz        |     35.00 |      8.00 |     16.00 |      7.00 |      4.00 |
+----+------------+-----------+-----------+-----------+-----------+-----------+

这是我想要达到的结果表:

+-----------+-----------+
| MyColumns |   Total   |
+-----------+-----------+
| Unknown 1 |     67.00 |
+-----------+-----------+
| Unknown 2 |     40.00 |
+-----------+-----------+
| Unknown 3 |     33.00 |
+-----------+-----------+
| Unknown 4 |     39.00 |
+-----------+-----------+
| Unknown 5 |     33.00 |
+-----------+-----------+

我已经弄清楚了上面未知列(第一个字段)的查询。但是,我很难使用下面的尝试代码来获取总列(第二个字段):

SELECT `COLUMN_NAME`
FROM  `INFORMATION_SCHEMA`.`COLUMNS` 
WHERE `TABLE_SCHEMA` = 'mydb' 
AND   `TABLE_NAME`   = 'source_table'
AND   `COLUMN_NAME` NOT LIKE 'ID'
AND   `COLUMN_NAME` NOT LIKE 'Name';

如果我能使用上面的代码获取总列(第二个字段),我将不胜感激。

更新 1: @Akina 回答 result_table — 已在此处引用更正 ''',COLUMN_NAME, '''.

+-----------+-----------+
| MyColumns |   Total   |
+-----------+-----------+
|     10.00 |     67.00 |
+-----------+-----------+
|     18.00 |     40.00 |
+-----------+-----------+
|      5.00 |     33.00 |
+-----------+-----------+
|     21.00 |     39.00 |
+-----------+-----------+
|      6.00 |     33.00 |
+-----------+-----------+

【问题讨论】:

  • 使用常用字符串函数根据获取的列名列表构建完整的查询文本,然后使用prepared statement执行该文本。

标签: mysql


【解决方案1】:
SELECT GROUP_CONCAT( CONCAT( 'SELECT ''',
                             COLUMN_NAME,
                             ''' Columns, SUM(`',
                             COLUMN_NAME,
                             '`) Total FROM mydb.source_table' )
                     SEPARATOR '\nUNION ALL\n' )
INTO @sql
FROM  INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'mydb' 
  AND TABLE_NAME   = 'source_table'
  AND COLUMN_NAME NOT IN ('ID', 'Name');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DROP PREPARE stmt;

fiddle

出于调试目的 - 首先只执行删除 INTO 子句的 SELECT 查询(您也可以编辑到SEPARATOR '\nUNION ALL\n' - 查询文本将更清晰地查看),检查构建的查询文本在语法上是否正确,然后执行它并检查它的输出是否正确。如果没有 - 编辑。

可能的问题来源 - 列名可能是保留字或可能包含空格或其他有问题的字符。在这种情况下,您必须在 CONCAT 中添加引号反引号来包装字符串文字。


附言。代码已编辑,所有提到的版本(和数据库名称 - 以使代码独立于 CurrentDB)添加到。

PPS。如果需要,可以将数据库和表名(甚至跳过的名称列表)转换为参数,从而使代码更加通用...

【讨论】:

  • 好的,我现在就试试这个。谢谢。
  • 我已在我的问题中将列保留名称编辑为 MyColumns。
  • 请查看我上面的更新以了解此答案的结果:您的回答给了我正确的总数,但我想知道为什么 MyColumns 获取的是第一行数据。我将它与我对问题中第一列查询所做的进行了比较,我认为与您没有区别。为什么你的回答给了我不同的结果——还在搞清楚。
  • 如果我删除了这个',COLUMN_NAME,' MyColumns, 我得到了正确的总数。但是,如果我删除了, SUM(',COLUMN_NAME,') Total,我将获得 MyColumns 中行的所有数据。太奇怪了。某处不见了。
  • @RickyBelmont True - 引用错误。正在编辑...完成。
【解决方案2】:

考虑以下几点:

DROP TABLE IF EXISTS my_bad_table;

CREATE TABLE my_bad_table
(ID SERIAL PRIMARY KEY
,Name VARCHAR(12) NOT NULL UNIQUE
,Unknown1 DECIMAL(5,2) NOT NULL
,Unknown2 DECIMAL(5,2) NOT NULL
,Unknown3 DECIMAL(5,2) NOT NULL
,Unknown4 DECIMAL(5,2) NOT NULL
,Unknown5 DECIMAL(5,2) NOT NULL
);

INSERT INTO my_bad_table VALUES
(1,'abc',10.00,18.00, 5.00,21.00, 6.00),
(2,'ghq',22.00,14.00,12.00,11.00,23.00),
(3,'xyz',35.00, 8.00,16.00, 7.00, 4.00);

DROP TABLE IF EXISTS my_good_table;
CREATE TABLE my_good_table AS
SELECT id bad_table_id
     , '1'+0 unknown
     , unknown1 score
  FROM my_bad_table 
 UNION
SELECT id 
     , '2'+0
     , unknown2
  FROM my_bad_table 
 UNION
SELECT id 
     , '3'+0 
     , unknown3
  FROM my_bad_table 
 UNION
SELECT id 
     , '4'+0 
     , unknown4
  FROM my_bad_table 
 UNION
SELECT id 
     , '5'+0 
     , unknown5
  FROM my_bad_table;


ALTER TABLE my_good_table ADD PRIMARY KEY(bad_table_id,unknown);
ALTER TABLE my_good_table ADD INDEX(score);
ALTER TABLE my_bad_table DROP COLUMN unknown1;
ALTER TABLE my_bad_table DROP COLUMN unknown2;
ALTER TABLE my_bad_table DROP COLUMN unknown3;
ALTER TABLE my_bad_table DROP COLUMN unknown4;
ALTER TABLE my_bad_table DROP COLUMN unknown5;

查询:

SELECT unknown
     , SUM(score) total
  FROM my_good_table
 GROUP
    BY unknown
 ORDER
    BY unknown;

+---------+-------+
| unknown | total |
+---------+-------+
|       1 | 67.00 |
|       2 | 40.00 |
|       3 | 33.00 |
|       4 | 39.00 |
|       5 | 33.00 |
+---------+-------+

【讨论】:

  • 据我了解,列名确实未知,不等于unknownX
  • @Akina 您可能是对的,但没有合理的理由说明列名未知。无论如何,这(或类似的东西)是表格最有可能的结构,无论列名如何。
  • 感谢@Strawberry。但是,未知列是在运行时可变创建的。意思是,它在运行时可以是任何列名。此外,忘了提及,未知列的数量也可以是任何数字,尽管在我的示例中我只显示了 5 个未知列。
  • @RickyBelmont 您只是支持如上所述重组表格的论点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-04
  • 1970-01-01
  • 1970-01-01
  • 2018-09-06
  • 1970-01-01
  • 1970-01-01
  • 2016-10-28
相关资源
最近更新 更多