2013-05-05 4 views
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 как вид?

+0

Это похоже на то, что вы ищете это присоединиться, но у меня возникают проблемы после набора данных. – j883376

+0

для каждой строки в 'fields' будет создан столбец в представлении. Из таблицы 'user_fields' самая младшая/самая новая запись выбирается для каждого« динамически »созданного coulmn – rauchmelder

+2

Это может помочь, если вы объясните, что вы пытаетесь выполнить. Это облегчит людям руководство. – kdmurray

ответ

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

Смежные вопросы