我正在尝试在MySQL中为表的所有列进行计算。
表格:bev
Jahr GKZ gesamt A B C
2017 1111000 88.519 855 888 814
2017 1112000 247.943 2.414 2.379 2.262
2017 1113000 253.106 2.290 2.343 2.289
2017 1113004 43.392 408 416 403
2017 1113008 12.383 137 134 124
2017 1113012 27.106 252 252 249
2017 1113016 41.673 391 410 398
2017 1113020 39.585 364 391 373
2017 1113024 10.075 63 73 74
2017 1113028 24.083 199 205 209
2017 1113032 8.745 63 77 65
2017 1113036 18.143 170 170 143
2017 1113040 27.921 243 215 251
表格:ja
GKZ Jahr ja_name
1001000 2017 K X
1002000 2017 K Y
5370000 2017 L Z
5370004 2017 Z1
5370012 2017 Z2
5370016 2017 Z3
5370020 2017 Z4
我已经获得函数中一列(第一列:gesamt)的计算:
CREATE DEFINER=`DB`@`%` FUNCTION `Total_Amount_Funct`(
bev_ID int(11),
bev_Total int(11),
ja_name VARCHAR(255),
ja_jahr int(11)) RETURNS int(11)
DETERMINISTIC
BEGIN
DECLARE Total_Amount int(11);
DECLARE kreis int(11);
DECLARE Total_Sum int(11);
SET kreis = (bev_ID / 1000) ;
SET Total_Sum = (SELECT SUM(b.gesamt)
FROM bev as b, ja as j
WHERE b.GKZ = j.GKZ
AND b.Jahr = j.Jahr
AND j.Jahr = ja_jahr
AND (MOD(b.GKZ, 1000) <> 0)
AND (MOD(b.GKZ, 1000) != 0)
AND NOT (MOD(b.GKZ, 1000) = 0)
AND (b.GKZ BETWEEN (kreis*1000 + 1) AND (((kreis+1)*1000)-1))
AND j.ja_name IS NOT NULL);
SET Total_Amount = bev_Total-Total_Sum;
RETURN (Total_Amount);
END
可以通过以下选择来调用此函数:
SELECT DISTINCT
bev.GKZ,
bev.Jahr,
bev.gesamt,
CASE WHEN (bev.GKZ % 1000 = 0) THEN
coalesce(Total_Amount_Funct(bev.GKZ, bev.gesamt, ja.ja_name, bev.Jahr), bev.gesamt)
ELSE bev.gesamt
END AS bev,
ja.ja_name
FROM
ja, bev
WHERE
bev.GKZ = ja.GKZ
AND bev.Jahr = ja.Jahr;
我真的很想将该功能应用于表的所有列。也许作为存储过程?也许作为动态列。我不知道。我已经使用动态列在MS SQL中解决了这个问题,但是我觉得翻译它比尝试完成作为存储过程的功能要花费更多的时间。
这些列的名称可以通过以下方式获得:
SELECT column_name
FROM information_schema.columns
WHERE table_name='bev'
and column_name not in ('Jahr','GKZ');
结果应该是:
GKZ Jahr gesamt bev ja_name
1111000 2017 88.519 88.519 K X
1112000 2017 247.943 247.943 K Y
1113000 2017 253.106 101.350 L Z
1113004 2017 43.392 43.392 Z1
1113012 2017 27.106 27.106 Z2
1113016 2017 41.673 41.673 Z3
1113020 2017 39.585 39.585 Z4
由于您仅在SUM中使用列,因此可以将列名称作为参数传递,并使用CASE语句相应地选择列。类似于:
CREATE FUNCTION `Total_Amount_Funct`(
bev_ID decimal(8,3),
bev_Total int,
ja_name VARCHAR(255),
ja_jahr int,
in_col varchar(10)
)
RETURNS int
DETERMINISTIC
BEGIN
DECLARE Total_Amount int(11);
DECLARE Total_Sum int(11);
SELECT
SUM(
case
when in_col='gesamt' then b.gesamt
when in_col='A' then b.A
when in_col='B' then b.B
when in_col='C' then b.C
end
) into Total_Sum
FROM bev as b
join ja as j on b.GKZ = j.GKZ AND b.Jahr = j.Jahr
WHERE
MOD(b.GKZ, 1000) != 0
AND b.GKZ BETWEEN bev_ID+1 AND bev_ID+999
AND j.ja_name IS NOT NULL
SET Total_Amount = bev_Total-Total_Sum;
RETURN (Total_Amount);
END
然后使用列名和正确的值调用该函数:
Total_Amount_Funct(bev.GKZ, bev.gesamt, ja.ja_name, bev.Jahr, 'gesamt'),
Total_Amount_Funct(bev.GKZ, bev.A, ja.ja_name, bev.Jahr, 'A')
...
注意,调用进行查询的函数会序列化您的SQL(在每一行上调用该函数都会在每一行上执行函数查询)。这会损害查询性能。
slaakso,
非常感谢您的回答。你今天是我的偶像:-)。
谢谢。
我可能有一个性能问题。
可以为表bev的所有列编写函数。我们可以将列名复制到临时表中:
CREATE TEMPORARY TABLE listColumns(
Columns_ID MEDIUMINT NOT NULL AUTO_INCREMENT ,
Columnsnamen varchar(256) ,
PRIMARY KEY (Columns_ID)
);
从系统信息中读取:
insert into listColumns (Columnsnamen)
SELECT column_name
FROM information_schema.columns
WHERE table_name='bev'
and column_name not in ('Jahr','GKZ');
此表如下:
Columns_ID Columnsnamen
1 gesamt
2 A
3 B
4 C
5
6
以这种方式,不必提及每个列名(该表包含约100列)。也许将光标放在Columns_ID上?
如果您对我有其他建议,那将很好。
谢谢您和亲切的朋友们>>
Ana