Stack Exchange 的同胞们,
我目前正在尝试创建一个以非常重要的方式重新格式化数据的程序。我得到一张票的数据列表(随机月份的摘要)。输入视图始终具有相同的列,但由于我必须将其与月份一起显示为列(通常在视图的 Monat 列中作为值输入)。Sooo,经过一些重大的研究、反复试验和许多令人头疼的事情,我必须让它发挥作用。该程序接受一个票号并“返回”该票的所有统计信息。
我这样做:
- 迭代每个不同的月份,构建一个 CREATE TEMPORARY TABLE 语句。
- 执行该语句,然后解除分配该语句
- 迭代每个票据值,使用 INSERT INTO ON DUPLICATE KEY UPDATE 语句将它们排序到临时表中(我重新构建、执行和取消分配每个迭代)
- 再次迭代每个不同的月份,构建最后一次更新以填充摘要列(我知道,我可以将其合并到第 1 步中,但我尽量保持这些步骤分开,只是为了更易于阅读,我一旦我完成让它按我想要的方式工作,就可以优化)。
- 选择临时表,所以它被返回
- 清理一些松散的地方,因为我是一个习惯性整洁的人。
好东西:它有效!坏事:它只适用于一个输入值。每当我将其更改为另一个票号时,这将需要不同的月份用于列它失败并显示“错误代码 1054,字段列表中的未知列”,指的是当前查询不应该具有的旧列(月份)。只要临时表的列相同,我可以根据需要多次运行该过程。每当我删除并重新创建过程或创建新连接时,此行为都会重置。
显然,我忘记在此过程中的某个地方做一个清理步骤,而且我对一般的 SQL 和特别是 MySQL 相当陌生,可能甚至不知道要寻找它:(。
帮助将不胜感激,谢谢,弗雷德
DELIMITER //
CREATE PROCEDURE proc_get_relevant_tickets(bID VARCHAR(10))
DETERMINISTIC
READS SQL DATA
BEGIN
# Declare storage vairables for withdrawing data from view
DECLARE ID, FiID, ZVB, ZNVB, ZGes, WVB, WNVB, WGes INTEGER;
DECLARE Mon VARCHAR(50);
DECLARE RowVerb, RowNVerb, RowGes, Counter INTEGER;
DECLARE verbucht, nichtverbucht, gesamt VARCHAR(50);
DECLARE currentticket INTEGER;
DECLARE statezges, statewges LONGTEXT;
# Declare runtime stuff
DECLARE done INT DEFAULT FALSE;
DECLARE declaration LONGTEXT;
DECLARE temptext VARCHAR(50);
DECLARE Months CURSOR FOR SELECT DISTINCT Monat FROM view_list_of_tickets t WHERE bID = t.ID;
DECLARE `Values` CURSOR FOR SELECT * FROM view_list_of_tickets t WHERE bID = t.ID;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
# Clean up in case something interrupted last execution
DROP TEMPORARY TABLE IF EXISTS temp_storage_5437485;
# If there are any entries to work upon
IF (SELECT COUNT(t.ID) FROM view_list_of_tickets t WHERE bID = t.ID > 0)
THEN
# Create temporary table to put the values into
SET declaration = 'CREATE TEMPORARY TABLE `temp_storage_5437485` (ID INTEGER PRIMARY KEY, TicketNr INTEGER, Category VARCHAR(50), ';
SET done = FALSE;
OPEN Months;
read_loop: LOOP
FETCH Months INTO temptext;
IF done THEN
LEAVE read_loop;
END IF;
SET declaration = CONCAT(declaration, '`', temptext, ' Zeit` INTEGER DEFAULT 0, ');
SET declaration = CONCAT(declaration, '`', temptext, ' Wert` INTEGER DEFAULT 0, ');
END LOOP;
CLOSE Months;
SET declaration = CONCAT(declaration, '`Gesamt Zeit` INTEGER, `Gesamt Wert` INTEGER);');
SELECT declaration INTO @declaration;
PREPARE stmt FROM @declaration;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# End of creating the storage container
# Cycle through values and input into temporary table
SET done = FALSE;
SET verbucht = 'Verbucht';
SET nichtverbucht = 'Nicht Verbucht';
SET gesamt = 'Gesamt';
SET currentticket = 0;
SET Counter = 0;
SET RowVerb = 1;
SET RowNVerb = 2;
SET RowGes = 3;
OPEN `Values`;
read_values: LOOP
FETCH `Values` INTO ID, FiID, ZVB, ZNVB, ZGes, WVB, WNVB, WGes, Mon;
IF done THEN
LEAVE read_values;
END IF;
# If a new ticket has been arrived at, increment the counters
IF currentticket > 0 AND ID <> currentticket THEN
SET currentticket = ID;
SET Counter = Counter + 1;
SET RowVerb = RowVerb + 3;
SET RowNVerb = RowNVerb + 3;
SET RowGes = RowGes + 3;
END IF;
IF currentticket = 0 AND ID <> currentticket THEN
SET currentticket = ID;
END IF;
# Insert first (Verbucht) row
SET declaration = CONCAT('INSERT INTO `temp_storage_5437485` (`ID`, `TicketNr`, `', Mon, ' Zeit`, `', Mon, ' Wert`) VALUES (');
SET declaration = CONCAT(declaration, RowVerb, ', ', ID, ', ', ZVB, ', ', WVB, ') ON DUPLICATE KEY UPDATE ');
SET declaration = CONCAT(declaration, '`', Mon, ' Zeit`=', ZVB, ', `', Mon, ' Wert`=', WVB, ';');
SELECT declaration INTO @declaration;
PREPARE stmt FROM @declaration;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# Insert second (Nicht Verbucht) row
SET declaration = CONCAT('INSERT INTO `temp_storage_5437485` (`ID`, `TicketNr`, `', Mon, ' Zeit`, `', Mon, ' Wert`) VALUES (');
SET declaration = CONCAT(declaration, RowNVerb, ', ', ID, ', ', ZNVB, ', ', WNVB, ') ON DUPLICATE KEY UPDATE ');
SET declaration = CONCAT(declaration, '`', Mon, ' Zeit`=', ZNVB, ', `', Mon, ' Wert`=', WNVB, ';');
SELECT declaration INTO @declaration;
PREPARE stmt FROM @declaration;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# Insert third (Gesamt) row
SET declaration = CONCAT('INSERT INTO `temp_storage_5437485` (`ID`, `TicketNr`, `', Mon, ' Zeit`, `', Mon, ' Wert`) VALUES (');
SET declaration = CONCAT(declaration, RowGes, ', ', ID, ', ', ZGes, ', ', WGes, ') ON DUPLICATE KEY UPDATE ');
SET declaration = CONCAT(declaration, '`', Mon, ' Zeit`=', ZGes, ', `', Mon, ' Wert`=', WGes, ';');
SELECT declaration INTO @declaration;
PREPARE stmt FROM @declaration;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
UPDATE temp_storage_5437485 SET Category = verbucht WHERE temp_storage_5437485.ID = RowVerb LIMIT 5;
UPDATE temp_storage_5437485 SET Category = nichtverbucht WHERE temp_storage_5437485.ID = RowNVerb LIMIT 5;
UPDATE temp_storage_5437485 SET Category = gesamt WHERE temp_storage_5437485.ID = RowGes LIMIT 5;
END LOOP;
CLOSE `Values`;
# End of cycling for values input
# Being calculating the total values
SET declaration = 'UPDATE temp_storage_5437485 SET `Gesamt Zeit` = (';
SET statezges = '';
SET statewges = '';
SET done = FALSE;
OPEN Months;
read_loop: LOOP
FETCH Months INTO temptext;
IF done THEN
LEAVE read_loop;
END IF;
# If not the first entry, add more
IF statezges <> '' THEN
SET statezges = CONCAT(statezges, ' + ');
END IF;
IF statewges <> '' THEN
SET statewges = CONCAT(statewges, ' + ');
END IF;
# Add column name
SET statezges = CONCAT(statezges, 'temp_storage_5437485.`', temptext, ' Zeit`');
SET statewges = CONCAT(statewges, 'temp_storage_5437485.`', temptext, ' Wert`');
END LOOP;
CLOSE Months;
SET declaration = CONCAT(declaration, statezges, '), `Gesamt Wert` = (', statewges, ') LIMIT 100000');
SELECT declaration INTO @declaration;
PREPARE stmt FROM @declaration;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# End calculating the total values
SELECT * FROM temp_storage_5437485;
DROP TEMPORARY TABLE IF EXISTS temp_storage_5437485;
ELSE
SELECT 'is null';
END IF;
DROP TEMPORARY TABLE IF EXISTS temp_storage_5437485;
END //
DELIMITER ;