Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL:Zeilen auswählen, gruppieren und in separate Spalten umwandeln :)

Ihre Daten sind etwas schwierig zu handhaben.

Um eine Pivot-Tabelle zu erstellen, müssen die Spalten eindeutig sein, mehr noch, dass auch fünf Kis erscheinen können.

Es ist ziemlich hässlich und funktioniert mit myslq 5.7

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

Abfrage 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     |      |                |

Auf DB Fiddle ansehen