К основному контенту

MySQL транспонирование

В этой статье я хотел бы поделиться методом для транспонирования строк в колонки. Самый простой пример, когда есть колонка, в которой указано имя поля и колонка с его значением (пример разобран тут). Но давайте предположим, что у нас есть таблица связи многие ко многим, в которых связаны, допустим, идентификатор пользователя и идентификатор системы, к которой он имеет доступ. А на выходе нам нужно получить таблицу, где колонками являются имена систем и, если пользователь имеет к ней доступ, в колонке с системой напротив его идентификатора стоял "X".

Исходные данные

Итак, у нас есть таблица-справочник с именами систем и у нас есть таблица соответствия идентификаторов пользователя и системы.

Step-by-step

1. Самое простое - нужно знать, как вывести "X" в выходную таблицу. С этим все просто:
SELECT 'X' AS col_name
2. Создадим промежуточную таблицу, в которой будут лежать наши данные:
DROP TABLE IF EXISTS tmp_results;


CREATE
TEMPORARY TABLE tmp_results AS
SELECT a.`id`,
       a.`employeeid`,
       s.`name`
FROM `systemaccess` AS a
LEFT OUTER JOIN `system` AS s ON a.systemid = s.id;
3. Нам нужно получить список систем, которые участвуют в выводе, тут тоже все просто:
SELECT DISTINCT `name` AS col_name
FROM tmp_results
4. Теперь нам нужно сделать динамическую трансформацию значений в имена колонок. В этом нам поможет функция GROUP_CONCAT. Основываясь на статье, которую я упомянул в самом начале и первом пункте нашей инструкции сформируем следующий запрос:
SELECT GROUP_CONCAT(CONCAT('IFNULL(MAX(CASE WHEN name=''',col_name,''' THEN ''',
                             (SELECT 'X' AS col_name),''' END), '''') AS "',col_name,'"')) AS systems
FROM
  ( SELECT DISTINCT `name` AS col_name
   FROM tmp_results ) system_col_names
Этот запрос сформирует следующую строку:
IFNULL(MAX(CASE
               WHEN name='SAP' THEN 'X'
           END), '') AS "SAP",
IFNULL(MAX(CASE
               WHEN name='1C' THEN 'X'
           END), '') AS "1C"
Т.е. при выборе данных БД проверит, есть ли значение с этой системой. Если есть, то она в колонку поставит "X", а графу назовет именем системы.

5. Следующее, что нам потребуется - это динамически сформированный список колонок для выбора основных данных. Тут можно воспользоваться функцией CONCAT.
SELECT CONCAT('
 SELECT employeeid, ',systems,'
 FROM tmp_results
 GROUP BY employeeid
 ORDER BY employeeid') INTO @query
6. Теперь все это подготавливаем и выполняем.
PREPARE STATEMENT
FROM @query;

EXECUTE STATEMENT;
В итоге получаем то, что нам нужно!

Весь код MySQL

DROP TABLE IF EXISTS tmp_results;


CREATE
TEMPORARY TABLE tmp_results AS
SELECT a.`id`,
       a.`employeeid`,
       s.`name`
FROM `systemaccess` AS a
LEFT OUTER JOIN `system` AS s ON a.systemid = s.id;


SELECT CONCAT('
 SELECT employeeid, ',systems,'
 FROM tmp_results
 GROUP BY employeeid
 ORDER BY employeeid') INTO @query
FROM
  ( SELECT GROUP_CONCAT(CONCAT('IFNULL(MAX(CASE WHEN name=''',col_name,''' THEN ''',
                                 (SELECT 'X' AS col_name),''' END), '''') AS "',col_name,'"')) AS systems
   FROM
     ( SELECT DISTINCT `name` AS col_name
      FROM tmp_results ) system_col_names) AS RESULT ;

PREPARE STATEMENT
FROM @query;

EXECUTE STATEMENT;

Комментарии

Популярные сообщения из этого блога

Прямые ссылки на файлы Google диска

В предыдущей статье я рассказал, как подключить свой JavaScript файл к блогу BLOGSPOT . Но для того, что бы их подключить нужны прямые ссылки на файл, а Google диск при предоставлении общего доступа к файлу выдает ссылку на предварительный просмотр, которая никак напрямую не ссылается на файл. Для Google диска прямая ссылка на файл - это ссылка на скачивание. Ниже описаны два способа создания ссылки на скачивание на примере файла prism.js.

OOP ALV GRID с HTML шапкой

В этой статье хочу постараться подробно описать и привести пример, как можно создать ALV отчет с таблицей на весь экран и с HTML шапкой вверху. Я не буду описывать начальный этап, где пишется селекционный экран или делается выборка данных. Будем считать, что основа у нас есть и нам нужно просто вывести данные. Главной изюминкой является то, что нужно вывести ALV GRID на экран без использования каких-либо дополнительных элементов на экране. Step-By-Step Шаг 1. Создание окна Создаем самое простое окно с номером 100. На него не нужно кидать никаких контейнеров. Оно нам нужно только для модулей PAI и PBO и вывода на него ALV GRID.

События для ведения таблиц

Как и всегда, в пылу проекта внезапно родилась Z табличка. Главный нюанс был в том, что она должна была хранить пароли для авторизации на стороннем сервере. Естественно, никто не хотел хранить пароли в открытом виде, а двустороннее шифрование SAP не умеет без сторонних пакетов и надстроек. Далее, все как обычно - придумали алгоритм, сделали табличку. Дело осталось за малым - нужно шифровать пароли, которые вводит пользователь. Делать отдельную программу нет смысла, поскольку ее функционал мало чем будет отличаться от сгенерированного. Вот здесь на помощь приходят события! С их помощью можно, наверное, все. По крайней мере, я не нашел чего-либо, что нельзя сделать с данными через события.