0

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

我不知道哪些数据将保存在这个数据库中。例如,有人想保存他的icq号码,而我以前不知道,他可以把它写到哪里?他动态创建了一个新字段,并且在后台完成了一个插入操作,fields并在 user_fields 中进行了一个插入操作,其中存储了新选项的新值。

user

id  username
1   rauchmelder

fields

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

结果应该是一个视图:

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

首先,这有意义吗?

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

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

4

1 回答 1

3

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

如果您fields提前知道,那么您可以对查询中的值进行硬编码:

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

但是由于您将有未知字段,那么您将需要使用准备好的语句来生成动态 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

于 2013-05-05T19:57:42.573 回答