对 SQL 表中的 x 到 x+n 列求和
Posted
技术标签:
【中文标题】对 SQL 表中的 x 到 x+n 列求和【英文标题】:Summing columns x through x+n in an SQL table 【发布时间】:2018-08-06 17:38:34 【问题描述】:我正在尝试。本质上,我有多个表,其中包含成绩和 user_id。我想总结所有成绩以得出一个总成绩列,而不指定列名,因为每个表的名称和列数都会发生变化。例如,一个表可能有列(user_id、calculations、prelab、deductions),而另一个可能有(user_id、accuracy、precision、graphs、prelab、deductions)。
我可以重命名列 col1、col2、col3、col4、col5 等,但我不知道如何绕过不同数量的列。
【问题讨论】:
您可以获取列名并从中构建查询:***.com/questions/1054984/… 这种问题可能是设计不佳的症状 【参考方案1】:据我所知,如果不直接在 SQL 中实际指定列名,就无法对列组求和。在我看来,这是一个设计糟糕的架构,但这是一个单独的主题。
在任何情况下,您都需要在每个表中创建一个新列,其中包含该特定表中所有成绩的总和,例如称为total em>,然后,做这样的事情:
select user_id, sum(table1.total, table2.total, table3.total)
from table1, table2, table3
where table1.user_id = table2.user_id
and table2.user_id = table3.user_id
group by user_id
【讨论】:
【参考方案2】:1) 您可以编写一些 pl/sql 来访问数据字典并获取列,然后构造动态 sql 来完成正确添加它们的工作。
2) 或者您可以在包含 user_id 和感兴趣列的总和的表上创建视图(视图本身可以通过编程方式构建 - 但这只需要发生一次,而不是每次您想要总数时)。
但与简单地修复您的架构相比,上述任何一个都可能是过度杀伤。
【讨论】:
【参考方案3】:以下过程可能会奏效。
它将在 INFORMATION_SCHEMA.COLUMNS 表中查找给定 tableName 的所有列名(不包括“userid” - 如果您使用的名称不同,这可能会发生变化)。 该过程还创建了一个临时表(这也有待改进 - 如果在创建之前存在,则最好执行“删除”)以将总和存储到一个点。 循环中的项目只是使用给定的 tableName 参数和来自游标的 columnName 构建一个 SQL UPDATE 语句并进行数学运算。 要对此进行测试(创建后):
调用 myProcedure('tableName');
DELIMITER //
DROP PROCEDURE IF EXISTS myProcedure //
CREATE PROCEDURE
myProcedure( tableName varchar(32) )
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE columnName varchar(64);
DECLARE cur1 CURSOR FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = tableName and COLUMN_NAME <> 'userid';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
CREATE TEMPORARY TABLE intermediateresults(userid integer, sumOfScores integer);
SET @st1 = CONCAT('INSERT INTO intermediateresults (SELECT DISTINCT userid, 0 FROM ',tableName,' )' );
PREPARE stmt3 FROM @st1;
EXECUTE stmt3;
looping: LOOP
FETCH cur1 into columnName;
IF done THEN
LEAVE looping;
END IF;
SET @st1 = CONCAT('UPDATE intermediateresults set sumOfScores = sumOfScores + COALESCE( (SELECT ', columnName, ' FROM ',tableName, ' t WHERE t.userid=intermediateresults.userid) , 0)' );
PREPARE stmt3 FROM @st1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
END LOOP;
CLOSE cur1;
SELECT * FROM intermediateresults;
DROP table intermediateresults;
END
//
DELIMITER ;
做这种事情时可能会感兴趣: INFORMATION_SCHEMA 还包含以下数据:DATA_TYPE:可用于测试特定列是否具有您期望的实际类型 - 可以将 DATA_TYPE='int' 等条件添加到游标定义以确保它实际上是一个 int(假设要求和的列实际上是 INT)ORDINAL_POSITION:如果您知道列的顺序,则可以使用它应该到达(例如,对于最后四个是内务处理的情况)TABLE_SCHEMA:上面的过程假定该表仅存在于当前默认模式中。使用它需要在过程中添加一个额外的参数,并在构造的 SQL 语句中稍作更改。
【讨论】:
以上是关于对 SQL 表中的 x 到 x+n 列求和的主要内容,如果未能解决你的问题,请参考以下文章
Oracle SQL 在字段更改时运行总计(仅在字段更改时对列求和)