简体   繁体   中英

MySQL, grouping multiple rows where the id is the same

I have inherited a lovely schema which has three fields: id, field_name, field_value . Now you can probably see how this is going to work, for each field that is added via the CMS it is added as a new row, while the id value is NOT unique.

But each field is not an individual entity, they should in fact be grouped by the id (which references the instance of the form that was submitted). As a side note I'd be interested to know what this schema pattern might be called?

//example db contents
1    name        Joe Blogs
1    email       joe@example.com
1    programme   sport
2    name        Dave
2    email       dave@example.com
2    programme   art

And of course I really want to be using one query to get selected fields grouped by the id field. Output as array( id => array( 'field' => 'value' , 'field' => 'value' ) ) etc

Typically I'd do the below, but I'd like to know if there is a pure SQL way to do this, cutting out the loop and processing at the bottom.

$existing = new stdClass;
$sql = "SELECT 'id','field_name','field_value'
                FROM table_name";
$results = $wpdb->get_results( $sql, ARRAY ); //using wordpress btw
        foreach ( $results as $k=>$r )
            $existing[$r['id']][$k] = $r;

You can use aggregate function and case to pivot the values,

SELECT  ID,
        MAX(CASE WHEN type = 'name' THEN value ELSE NULL end) Name,
        MAX(CASE WHEN type = 'email' THEN value ELSE NULL end) email,
        MAX(CASE WHEN type = 'programme' THEN value ELSE NULL end) programme
FROM table1
GROUP BY ID

SQLFiddle Demo

or in the future if you are planning to add another type without altering the query, you can use prepared statements,

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'MAX(CASE WHEN type = ''',
      type,
      ''' then value ELSE NULL end) AS ',
      type
    )
  ) INTO @sql
FROM table1;

SET @sql = CONCAT('SELECT  ID, ', @sql, ' 
                   FROM table1 
                   GROUP BY ID');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SQLFiddle Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM