聚合函数过程

时间:2017-11-11 10:39:24

标签: sql mariadb

我必须使用两个参数制作一个程序:kolaggkol显然是列,agg是一个聚合函数。

假设我有下表:

+---------+---------+
| X (int) | Y (int) |
+---------+---------+
| 5       | 2       |
| 4       | 4       |
+---------+---------+

我想调用('X','sum')这个程序 - 然后它会显示SELECT SUM(x) FROM table所以9. ('Y','avg')显示SELECT AVG(y) FROM table所以3。

我有一些东西,但在涉及SUMAVGMINMAX时它不起作用,它只适用于计数(适用于SUMAVGMINMAX显示0,不知道原因):

-- I skipped some lines in procedure, only this is necessary

BEGIN
  IF(kol IN (select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where 
  TABLE_NAME='table')) THEN 

    -- getting every column for table above
    SELECT (
      CASE 
        WHEN agg='SUM' THEN sum(kol)
        WHEN agg='COUNT' THEN count(kol)
        WHEN agg='AVG' THEN avg(kol)
        WHEN agg='MAX' THEN max(kol)
        WHEN agg='MIN' THEN min(kol)
    END) Result FROM table;
  END IF;
END

1 个答案:

答案 0 :(得分:1)

您可以使用以下解决方案:

DELIMITER //

CREATE PROCEDURE testProc (IN col VARCHAR(10), IN agg VARCHAR(10))
  BEGIN
    SET @select = '';

    -- get the select part with the aggregation function.
    -- using UPPER to allow case-insensitive input.
    SELECT CASE 
      WHEN UPPER(agg) = 'SUM' THEN CONCAT('SUM(', col, ')')
      WHEN UPPER(agg) = 'COUNT' THEN CONCAT('COUNT(', col, ')')
      WHEN UPPER(agg) = 'AVG' THEN CONCAT('AVG(', col, ')')
      WHEN UPPER(agg) = 'MAX' THEN CONCAT('MAX(', col, ')')
      WHEN UPPER(agg) = 'MIN' THEN CONCAT('MIN(', col, ')')
    END
    INTO @select;

    -- create and prepare the full statement.
    SET @stmt = CONCAT('SELECT ', @select, ' AS Result FROM table_name');
    PREPARE stmtExec FROM @stmt;

    -- execute the statement.
    EXECUTE stmtExec;
  END//

我使用您的数据尝试了此解决方案并获得以下结果:

CALL testProc('x', 'SUM');      -- 9
CALL testProc('y', 'SUM');      -- 6
CALL testProc('x', 'COUNT');    -- 2
CALL testProc('y', 'COUNT');    -- 2
CALL testProc('x', 'AVG');      -- 4.500
CALL testProc('y', 'AVG');      -- 3.000
CALL testProc('x', 'MAX');      -- 5
CALL testProc('y', 'MAX');      -- 4
CALL testProc('x', 'MIN');      -- 4
CALL testProc('y', 'MIN');      -- 2

您不能将column参数用作聚合函数的参数。但是你可以创建一个字符串并在准备好的语句中使用它(参见上面的解决方案):

  

用户变量旨在提供数据值。它们不能直接在SQL语句中用作标识符或标识符的一部分,例如在需要表或数据库名称的上下文中,或作为SELECT等保留字。

     

这个原则的一个例外是用户变量不能用于提供标识符,就是在构造一个字符串以用作稍后执行的预准备语句时。在这种情况下,用户变量可用于提供语句的任何部分。

     

来源: https://dev.mysql.com/doc/refman/5.7/en/user-variables.html

在评论中提供了一些其他信息后,我将PROCEDURE更改为以下解决方案。在那里你也得到了结果的列名和聚合函数:

DELIMITER //

CREATE PROCEDURE testProc (IN col VARCHAR(10), IN agg VARCHAR(10))
  BEGIN
    SET @select = '';

    -- get the select part with the aggregation function.
    -- using UPPER to allow case-insensitive input.
    SELECT CASE 
      WHEN UPPER(agg) = 'SUM' THEN CONCAT('SUM(', col, ')')
      WHEN UPPER(agg) = 'COUNT' THEN CONCAT('COUNT(', col, ')')
      WHEN UPPER(agg) = 'AVG' THEN CONCAT('AVG(', col, ')')
      WHEN UPPER(agg) = 'MAX' THEN CONCAT('MAX(', col, ')')
      WHEN UPPER(agg) = 'MIN' THEN CONCAT('MIN(', col, ')')
    END
    INTO @select;

    -- create and prepare the full statement.
    SET @stmt = CONCAT('SELECT CONCAT(\'', col, '|', UPPER(agg), '|\', ', @select, ') AS Result FROM table_name');
    PREPARE stmtExec FROM @stmt;

    -- execute the statement.
    EXECUTE stmtExec;
  END//

所以我再次测试了这个解决方案,现在得到以下结果:

CALL testProc('x', 'SUM');      -- x|SUM|9
CALL testProc('y', 'SUM');      -- y|SUM|6
CALL testProc('x', 'COUNT');    -- x|COUNT|2
CALL testProc('y', 'COUNT');    -- y|COUNT|2
CALL testProc('x', 'AVG');      -- x|AVG|4.5000
CALL testProc('y', 'AVG');      -- y|AVG|3.0000
CALL testProc('x', 'MAX');      -- x|MAX|5
CALL testProc('y', 'MAX');      -- y|MAX|4
CALL testProc('x', 'MIN');      -- x|MIN|4
CALL testProc('y', 'MIN');      -- y|MIN|2