mysql - 行在 View 中表示为列

标签 mysql

就我而言,我有一种保存用户数据的创造性方法。让我解释一下:

我不知道这个数据库中要保存哪些数据。比如有人要保存他的icq号码,我之前不知道,他可以写到哪里呢?他动态创建了一个新字段,并在后台在 fields 中完成了插入,并在存储新选项的新值的 user_fields 中插入。

用户:

id  username
1   rauchmelder

字段:

id  name
1   firstname
2   lastname

user_fields:(旧值和当前值一样存储,只应使用最新的条目)

id  user_id  fields_id  value        date
1   1        1          Chris        1.Mai
1   1        2          Rauch        1.Mai
1   1        1          Christopher  2.Mai

结果应该是一个 View :

user.id  user.username   fields.firstname  fields.lastname
1        rauchmelder     Christopher       Rauch

首先,它是否有意义?

其次,我应该在MySQL中解决还是在应用程序中解决?

第三,如何在MySQL as a View中解决这个问题?

最佳答案

为了将数据放入列中,您可以使用带有 CASE 表达式的聚合函数将行数据转换为列。

如果您的字段是提前知道的,那么您可以在查询中硬编码这些值:

select u.id,
  u.username,
  max(case when f.name = 'firstname' then uf.value end) firstname,
  max(case when f.name = 'lastname' then uf.value end) lastname
from user u
left join
(
  select uf1.*
  from user_fields uf1
  inner join
  (
    select max(date) maxDate, user_id, fields_id
    from user_fields
    group by user_id, fields_id
  ) uf2
    on uf1.date = uf2.maxdate
    and uf1.user_id = uf2.user_id
    and uf1.fields_id = uf2.fields_id
) uf
  on u.id = uf.user_id
left join fields f
  on uf.fields_id = f.id
group by u.id, u.username;

参见 SQL Fiddle with Demo

但由于您将拥有未知字段,因此您需要使用 prepared statement生成要执行的动态 SQL。语法类似于:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(CASE WHEN f.name = ''',
      name,
      ''' THEN uf.value END) AS `',
      name, '`'
    )
  ) INTO @sql
FROM fields;


SET @sql 
  = CONCAT('SELECT u.id,
            u.username, ', @sql, ' 
           from user u
           left join
           (
             select uf1.*
             from user_fields uf1
             inner join
             (
               select max(date) maxDate, user_id, fields_id
               from user_fields
               group by user_id, fields_id
             ) uf2
               on uf1.date = uf2.maxdate
               and uf1.user_id = uf2.user_id
               and uf1.fields_id = uf2.fields_id
           ) uf
             on u.id = uf.user_id
           left join fields f
             on uf.fields_id = f.id
           group by u.id, u.username');

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

参见 SQL Fiddle with Demo

关于mysql - 行在 View 中表示为列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16388155/

相关文章:

MySql - 在两个表中查找重复项并删除它们

php - 使用 PDO 的多个数据库

mysql - 根据表中的另一列添加序列无列

php - 如何避免基于 2 个表的重复 slug 并创建唯一的 slug

mysql - VB MySql 优化

mysql - 提高长 VARCHAR 字段的排序性能

MySQL 枚举与集合

php - 如何在循环内对 php mysql 中的查询结果进行子查询

php - 向数据库询问用户名列表

html - 如何将html表数据插入mysql数据库