sql >> Base de Datos >  >> RDS >> Mysql

cómo hacer valores de fila a columna dinámicamente en mysql

Como nadie más ha respondido. Te doy mi idea. La base de todo es

CREATE TABLE tank
(`Tank_ID` int, `Tank` varchar(6))
;

INSERT INTO tank
(`Tank_ID`, `Tank`)
VALUES
(1, 'Tank 1'),
(2, 'Tank 2'),
(3, 'Tank 3'),
(4, 'Tank 4'),
(5, 'Tank 5');

CREATE TABLE tank_detail
(`Tank_ID` int, `Receipt` int, `Date` date);

INSERT INTO tank_detail
(`Tank_ID`, `Receipt`, `Date`)
VALUES
(1, 1000, '2019-07-10'),
(2, 2000, '2019-07-10'),
(3, 3000, '2019-07-10'),
(1, 0, '2019-07-10'),
(1, 0, '2019-07-15'),
(3, 0, '2019-07-15'),
(2, 0, '2019-07-15'),
(3, 0, '2019-07-15'),
(1, 250, '2019-07-15'),
(2, 200, '2019-07-15'),
(3, 800, '2019-07-15'),
(1, 250, '2019-07-15'),
(4, 350, '2019-07-15'),
(1, 0, '2019-07-20'),
(2, 0, '2019-07-20'),
(3, 0, '2019-07-20'),
(4, 0, '2019-07-20'),
(1, 300, '2019-07-20'),
(2, 1200, '2019-07-20'),
(3, 1400, '2019-07-20'),
(4, 900, '2019-07-20'),
(5, 20, '2019-07-20'),
(1, 500, '2019-07-20');

A partir de eso, construyo primero una declaración Sql estática

 Select Date,Sum(recsum) as Receipt
  , Sum(a1) as 'Tanl 1'
  , Sum(a2) as 'Tanl 2'
  , Sum(a3) as 'Tank 3'
  , Sum(a4) as 'Tanl 4'
  , Sum(a5) as 'Tanl 5'
 From
  (Select tank_detail.Tank_ID tankid,Date,Sum(Receipt) recsum
   , if (tank_detail.Tank_ID = 1, Sum(Receipt),0) as a1
   , if (tank_detail.Tank_ID = 2, Sum(Receipt),0) as a2
   , if (tank_detail.Tank_ID = 3, Sum(Receipt),0) as a3
   , if (tank_detail.Tank_ID = 4, Sum(Receipt),0) as a4
   , if (tank_detail.Tank_ID = 5, Sum(Receipt),0) as a5
  From tank_detail 
  Group by tank_detail.Tank_ID,Date) td1
 Group by Date  ;

Y a partir de eso construyo un procedimiento almacenado con un bucle

CREATE DEFINER=`root`@`localhost` PROCEDURE `procedure_Receipt_Tank`()
BEGIN
DECLARE bDone int DEFAULT 0;
DECLARE tanknumber int DEFAULT 0;
DECLARE tabkname VARCHAR(10);
DECLARE Tempvar LONGTEXT DeFAULT '';
DECLARE Tempvar2 LONGTEXT DeFAULT '';

DECLARE curs1 CURSOR FOR SELECT Tank_ID,Tank From tank;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;

OPEN curs1;
SET Tempvar = CONCAT(Tempvar , 'Select Date,Sum(recsum) as Receipt ');
SET Tempvar2 = CONCAT(Tempvar2 , ' From ');
SET Tempvar2 = CONCAT(Tempvar2 , '(Select tank_detail.Tank_ID
tankid,Date,Sum(Receipt) recsum ');
read_loop: LOOP

    FETCH curs1 INTO tanknumber,tabkname;
    IF bDone = 1 THEN
        LEAVE read_loop;
    END IF;        
    SET Tempvar = CONCAT(Tempvar , ' , Sum(a',tanknumber,') as "',tabkname,'"');
    SET Tempvar2 = CONCAT(Tempvar2 , ', if (tank_detail.Tank_ID = ',tanknumber,',
    Sum(Receipt),0) as a',tanknumber,' ');
 END LOOP read_loop;
CLOSE curs1;
SET Tempvar = CONCAT(Tempvar ,Tempvar2,' From tank_detail ');
SET Tempvar = CONCAT(Tempvar ,' Group by tank_detail.Tank_ID,Date) td1');
SET Tempvar = CONCAT(Tempvar ,' Group by Date;');
SET @v_Query =  '';
SET @v_Query = CONCAT(@v_Query ,  Tempvar);
PREPARE stmt FROM @v_Query;
execute stmt;
#Select Tempvar;        
END

Puede llamarlo usando el procedimiento de llamada_Receipt_Tank (); personalmente agregaría un marco de tiempo en el que desea los datos. Para esto, agrega al procedimiento almacenado la fecha desde la fecha y también tiene que agregar una fecha al procedimiento de llamada. El mayor problema es que este procedimiento almacenado genera una instrucción Select, que ejecuta al final. tempvar es de texto largo y puede tener hasta 4 gb