2017-11-11 106 views
1

我必须做两个参数的程序: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

我有事,但它不当它涉及到SUM,AVG,MINMAX,它只适用于计数(SUM,AVG,MINMAX显示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

您可以使用像一个解决方案如下:

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 

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

用户变量旨在提供数据值。它们不能在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 
+0

好吧,谢谢你,但我早该添加是我也想在选择中显示输入参数,如果我添加col和agg到concat,他们不工作,输出应该是这样的 - x |总和| 9 – jakub1998

+0

@ jakub1998 - 查看具有预期结果的更新答案。 –

+0

它的工作原理,非常感谢! – jakub1998