2017-11-11 45 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