就我而言,我有一种保存用户数据的创造性方法。让我解释一下:
我不知道这个数据库中要保存哪些数据。比如有人要保存他的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;
但由于您将拥有未知字段,因此您需要使用 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;
关于mysql - 行在 View 中表示为列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16388155/