对 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 在字段更改时运行总计(仅在字段更改时对列求和)

Postgres - 如何对窗口函数列的每 x 行求和?

Oracle Query 按另一个表中的每个日期范围对一列求和

CASE 基于布尔值对列求和

Oracle SQL:如何对每行的每 x 个后续行求和