sql >> Database >  >> RDS >> Mysql

hoe rijwaarden dynamisch naar kolom te maken in mysql

Zoals niemand anders heeft geantwoord. Ik geef je mijn idee. Basis voor iedereen is

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');

Van daaruit bouw ik eerst een statische Sql-instructie

 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  ;

En van daaruit bouw ik een opgeslagen procedure met een lus

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

Je kunt het aanroepen door call procedure_Receipt_Tank();Ik zou persoonlijk een tijdsbestek toevoegen waarin je de gegevens wilt. Hiervoor voeg je de opgeslagen procedure datefrom date toe en je moet ook een datum toevoegen aan de call procedure. Het grootste probleem is dat deze opgeslagen procedure een Select-instructie bouwt, die aan het einde wordt uitgevoerd. tempvar is longtext en kan tot 4 GB zijn




  1. Wijs hosttoegangsrechten opnieuw toe aan MySQL-gebruiker

  2. JDBC-verbinding met Oracle-database met behulp van TLS-certificaat

  3. Twee Laravel-applicaties op dezelfde server conflicteren met elkaar

  4. Uw SQL Server-workload leren kennen