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

MySQL:選択し、グループ化して、行を別々の列に変換します:)

    データの処理はやや困難です。

    ピボットテーブルを作成するには、列が一意である必要があります。さらに、5つのkiが表示される可能性があります。

    それはかなり醜く、myslq5.7で動作します

    スキーマ(MySQL v5.7)

    CREATE TABLE employees (
      `id` INTEGER,
      `emp` VARCHAR(5)
    );
    
    INSERT INTO employees
      (`id`, `emp`)
    VALUES
      ('1', 'emp-A'),
      ('2', 'emp-B'),
      ('3', 'emp-C');
    
    CREATE TABLE relatives (
      `id` INTEGER,
      `emp_id` INTEGER,
      `relation` VARCHAR(6),
      `relative` VARCHAR(8),
      `birthdate` DATE
    );
    
    INSERT INTO relatives
      (`id`, `emp_id`, `relation`, `relative`, `birthdate`)
    VALUES
      ('1', '1', 'spouse', 'spouse-A', '1970-01-01'),
      ('2', '1', 'kid', 'kid-A1', '1971-01-02'),
      ('3', '1', 'kid', 'kid-A2', '1972-01-01'),
      ('4', '1', 'kid', 'kid-A3', '1973-01-01'),
      ('5', '2', 'spouse', 'spouse-B', '1980-02-01'),
      ('6', '2', 'kid', 'kid-B1', '1981-02-01'),
      ('7', '2', 'kid', 'kid-B2', '1982-02-01'),
      ('8', '3', 'kid', 'kid-C1', '1991-03-01'),
      ('9', '3', 'kid', 'kid-C2', '1992-03-01');
    

    クエリ#1

    SELECT
      GROUP_CONCAT(DISTINCT
        CONCAT(
          'MAX(case when `relation` = "',
         `relation`,
          '" then `relation` end) AS `',
          relation, '`',
          ',MAX(case when `relation` = "',
         `relation`,
          '" then `birthdate` end) AS `',
          'birthdate_',relation, '`'      
        )
        ORDER BY rownumber
      ) INTO @sql
    FROM
      (SELECT 
        `relation`
        ,rownumber
    FROM 
        employees e
        INNER JOIN 
        (SELECT
        IF(`relation` = 'kid',IF (@empid = `emp_id`,@rn:= @rn+1,@rn:= 1),IF (@empid = `emp_id`,@rn:= @rn,@rn:= 0)) rownumber
         ,IF(`relation` = 'kid',CONCAT(`relation`,@rn),`relation`) relation
        , `relative`
        , `birthdate`
        ,@empid := `emp_id` emp_id
    FROM
        (SELECT 
            * 
        FROM 
            relatives
        ORDER BY `emp_id`,FIELD(`relation`,"spouse","kid"),`birthdate`) rel
        ,(SELECT @empid := 0) a1
        ,(SELECT @rn := 0) a2) r ON e.id = r.emp_id) t1
        ;
    
    SET @sql = CONCAT("SELECT MIN(`emp`), ", @sql, " 
                      FROM   (SELECT 
                                `emp_id`,
                                `emp` ,
                                `relation`
                                ,rownumber
                                , `relative`
                                , `birthdate`
                            FROM 
                                employees e
                                INNER JOIN 
                                (SELECT
                                IF(`relation` = 'kid',IF (@empid = `emp_id`,@rn:= @rn+1,@rn:= 1),IF (@empid = `emp_id`,@rn:= @rn,@rn:= 0)) rownumber
                                 ,IF(`relation` = 'kid',CONCAT(`relation`,@rn),`relation`) 'relation'
                                , `relative`
                                , `birthdate`
                                ,@empid := `emp_id` 'emp_id'
                            FROM
                                (SELECT 
                                    * 
                                FROM 
                                    relatives
                                ORDER BY `emp_id`,FIELD(`relation`,'spouse','kid'),`birthdate`) rel
                                ,(SELECT @empid := 0) a1
                                ,(SELECT @rn := 0) a2) r ON e.id = r.emp_id) t1 
                       GROUP BY `emp_id`");
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    
    | MIN(`emp`) | spouse | birthdate_spouse | kid1 | birthdate_kid1 | kid2 | birthdate_kid2 | kid3 | birthdate_kid3 |
    | ---------- | ------ | ---------------- | ---- | -------------- | ---- | -------------- | ---- | -------------- |
    | emp-A      | spouse | 1970-01-01       | kid1 | 1971-01-02     | kid2 | 1972-01-01     | kid3 | 1973-01-01     |
    | emp-B      | spouse | 1980-02-01       | kid1 | 1981-02-01     | kid2 | 1982-02-01     |      |                |
    | emp-C      |        |                  | kid1 | 1991-03-01     | kid2 | 1992-03-01     |      |                |
    

    DBフィドルで表示




    1. MySQLのDistinctの反対

    2. SQLServerでのLIKEとCONTAINS

    3. Oracle SQL Developerで外部キーを作成する方法は?

    4. 1 つの SQL ステートメントで varchar[n] フィールドのサイズを取得する方法は?