MySQL: как развернуть неизвестные пары имя-значение? - PullRequest
1 голос
/ 03 апреля 2011

Скажите, что у меня есть следующее:

-------------------------------------
| id | user_id | name       | value |
=====================================
| 1  | 10      | First Name | John  |
-------------------------------------
| 1  | 10      | Last Name  | Doe   |
-------------------------------------
| 1  | 10      | Age        | 25    |
-------------------------------------

Предположим, я не знаю, что "Имя", "Фамилия" и "Возраст" являются значениями в столбце name таблицы.Как мне запросить эту таблицу, чтобы получить что-то вроде этого:

------------------------------------------
| user_id | First Name | Last Name | Age |
==========================================
| 10      | John       | Doe       | 25  |
------------------------------------------

1 Ответ

1 голос
/ 03 апреля 2011

У Mysql нет встроенного способа решить эту проблему простым способом, о котором я знаю. Вам нужно будет создать некоторую логику. Я считаю, что вам придется создать хранимую процедуру или написать некоторую логику в коде вашего приложения, которая будет выполнять следующие действия:

  1. Запрос для всех отдельных полей "name"
  2. Динамически создавать и выполнять запрос со всеми полями, повернутыми, как описано в http://en.wikibooks.org/wiki/MySQL/Pivot_table

Если вы хотите сделать это полностью на стороне mysql, вы можете использовать динамический sql в хранимой процедуре, как описано в http://www.java2s.com/Code/SQL/Procedure-Function/EXECUTEdynamicSQLcommand.htm.

Вот процедура, которая должна работать для вас:

DROP PROCEDURE myProc;
delimiter $$
CREATE PROCEDURE myProc ()
BEGIN
    DECLARE this_name varchar(20);
    DECLARE done INT DEFAULT 0;
    DECLARE cur1 CURSOR FOR SELECT distinct name FROM user_info;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    SET @sql='select user_info_1.user_id';
    OPEN cur1;
    read_loop: LOOP
        FETCH cur1 INTO this_name;
        IF  done THEN 
            LEAVE read_loop;
        END IF;

        SET @sql=CONCAT(@sql, ", (select value from user_info where user_info.user_id = user_info_1.user_id and user_info.name = '", this_name, "') as '", this_name, "'");
    END LOOP;
    SET @sql=CONCAT(@sql, ' from (select distinct user_id from user_info) user_info_1');
    PREPARE s1 FROM @sql;
    EXECUTE s1;
    DEALLOCATE PREPARE s1;
END$$

Теперь, как говорится, будьте осторожны с этой структурой базы данных. Будьте осторожны, чтобы не перегружать проблему. Кроме того, вы отказываетесь от большого количества функциональных возможностей, которые база данных могла бы предоставить для вас, и будет очень трудно или невозможно реализовать уникальные ограничения, внешние ключи и т. Д. Многие инструменты CRM пытались пойти по этому пути, с катастрофическими результатами, и вместо этого сегодня они обычно просто автоматически изменяют базовую таблицу, добавляя новые столбцы по мере необходимости. Вы можете вместо этого рассмотреть этот подход.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...