sql >> データベース >  >> RDS >> Mysql

mysqlで行の値を列に動的に作成する方法

    他の誰も答えていないので。私はあなたに私の考えを与えます。すべての基礎は

    です。
    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');
    

    それから、最初に静的SQLステートメントを作成します

     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  ;
    

    そして、そこからループを使用してストアドプロシージャを構築します

    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
    

    call procedure_Receipt_Tank();を使用して呼び出すことができます。個人的には、データが必要な時間枠を追加します。これには、ストアドプロシージャのdatefrom dateに追加し、呼び出しプロシージャに日付を追加する必要があります。最大の問題はこのストアドプロシージャはSelectステートメントを作成し、最後に実行します。 tempvarはロングテキストで、最大4GBまで可能です




    1. 明示的結合と暗黙的結合?

    2. OracleのCOMPOSE()関数

    3. Laravelの読み取りと書き込みの接続が同期していません

    4. インデックスを使用したpostgresのクエリプラン