sql >> Database teknologi >  >> RDS >> Mysql

hvordan man laver rækkeværdier til kolonne dynamisk i mysql

Da ingen andre har svaret. Jeg giver dig min idé. Grundlaget for alle er

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

Ud fra det bygger jeg først en statisk SQL-sætning

 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  ;

Og ud fra det bygger jeg en lagret procedure med en loop

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

Du kan kalde det ved at bruge call procedure_Receipt_Tank(); Jeg ville personligt tilføje en tidsramme, hvor du vil have data. For dette tilføjer du til den lagrede procedure fra dato, og du skal også tilføje en dato til opkaldsproceduren. Det største problem er at denne lagrede procedure bygger en Select-sætning, som den udfører til sidst. tempvar er lang tekst og kan være op til 4 gb




  1. Log registreringsændringer i SQL-server i en revisionstabel

  2. MySQL - Lav én post ud af en kolonne

  3. at bruge Array_append giver mig syntaksfejl, når jeg opretter PostgreSQL-funktion

  4. Gem byte array i sql server