5

より動的にするために2つのパラメーターが渡される単純なストアドプロシージャをまとめました。これは、「最初の2桁とレコード数」セクションの準備されたステートメントを使用して行いました。

私が確信していないのはSET vTotalFT、プリペアドステートメントを使用してセクションを動的にすることができるかどうかです。

現時点では、テーブル名とフィールドをハードコーディングする必要があります。vTotalFT準備された動的SQLステートメントに基づいて変数を割り当てたいのですが、構文がわかりません。プロシージャを呼び出すと、分析に使用するテーブルとフィールドを指定できるという考え方です。

CREATE PROCEDURE `sp_benfords_ft_digits_analysis`(vTable varchar(255), vField varchar(255))
    SQL SECURITY INVOKER
BEGIN

    -- Variables
    DECLARE vTotalFT int(11);

    -- Removes existing table
    DROP TABLE IF EXISTS analysis_benfords_ft_digits;

    -- Builds base analysis table
    CREATE TABLE analysis_benfords_ft_digits
    (
        ID int(11) NOT NULL AUTO_INCREMENT,
        FT_Digits int(11),
        Count_of_Records int(11),
        Actual decimal(18,3),
        Benfords    decimal(18,3),
        Difference Decimal(18,3),
        AbsDiff decimal(18,3),
        Zstat decimal(18,3),
        PRIMARY KEY (ID),
        KEY id_id (ID)
    );

    -- First Two Digits and Count of Records
    SET @s = concat('INSERT INTO analysis_benfords_ft_digits
                        (FT_Digits,Count_of_Records)
                            select substring(cast(',vField,' as char(50)),1,2) as FT_Digits, count(*) as Count_of_Records
                            from ',vTable,'
                            where ',vField,' >= 10
                            group by 1');

    prepare stmt from @s;
    execute stmt;
    deallocate prepare stmt;

    SET vTotalFT = (select sum(Count_of_Records) from
                            (select substring(cast(Gross_Amount as char(50)),1,2) as FT_Digits, count(*) as Count_of_Records
                                from supplier_invoice_headers
                                where Gross_Amount >= 10
                                group by 1) a);


    -- Actual
    UPDATE analysis_benfords_ft_digits
    SET Actual = Count_of_Records / vTotalFT;

    -- Benfords
    UPDATE analysis_benfords_ft_digits
    SET Benfords = Log(1 + (1 / FT_Digits)) / Log(10);

    -- Difference
    UPDATE analysis_benfords_ft_digits
    SET Difference = Actual - Benfords;

    -- AbsDiff
    UPDATE analysis_benfords_ft_digits
    SET AbsDiff = abs(Difference);

    -- ZStat
    UPDATE analysis_benfords_ft_digits
    SET ZStat = cast((ABS(Actual-Benfords)-IF((1/(2*vTotalFT))<ABS(Actual-Benfords),(1/(2*vTotalFT)),0))/(SQRT(Benfords*(1-Benfords)/vTotalFT)) as decimal(18,3));
4

2 に答える 2

8

まず、動的なテーブル/列名を使用するには、の最初のクエリのように文字列/プリペアドステートメントを使用する必要があります@s。次に、クエリ内から戻り値を取得するにはCOUNT()、を使用する必要がありますSELECT .. INTO @vTotalFT

必要なのは次のとおりです。

SET @vTotalFTquery = CONCAT('(select sum(Count_of_Records) INTO @vTotalFT from
                        (select substring(cast(', vField, ' as char(50)),1,2) as FT_Digits, count(*) as Count_of_Records
                            from ', vTable, '
                            where ', vField, ' >= 10
                            group by 1) a);');
PREPARE stmt FROM @vTotalFTquery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

注意:変数名がからvTotalFTに変更されました@vTotalFT。がないと機能しないようです@。また@vTotalFT、クエリの外/前で宣言された場合、変数は機能しないため、エラーまたは空の結果が発生した場合は、原因となる可能性があります。

于 2012-07-27T17:13:47.903 に答える
0
SELECT CONCAT (
        'SELECT DATE(PunchDateTime) as day , '
        ,GROUP_CONCAT('GROUP_CONCAT(IF(PunchEvent=', QUOTE(PunchEvent), ',PunchDateTime,NULL))
       AS `', REPLACE(PunchEvent, '`', '``'), '`')
        ,'
         FROM     tbl_punch
         GROUP BY DATE(PunchDateTime) 
         ORDER BY PunchDateTime ASC
       '
        )
INTO @sql
FROM (
    SELECT DISTINCT PunchEvent
    FROM tbl_punch
    ) t;

PREPARE stmt
FROM @sql;

EXECUTE stmt;

DEALLOCATE PREPARE stmt;
于 2016-08-27T09:02:24.390 に答える