Сводная таблица в Mysql с большим количеством динамических столбцов - PullRequest
2 голосов
/ 28 марта 2019

У меня проблемы с созданием таблицы PIVOT в MySQL. У меня есть следующая таблица. (Это уменьшенная демонстрационная таблица. Реальная имеет 4000 акций для 10 сделок и 20 значений измерений.)

     CREATE TABLE `levermann` (
       `RecNum` bigint(20) NOT NULL AUTO_INCREMENT,
       `Tradedate` date DEFAULT NULL,
       `Stock_Short` varchar(50) DEFAULT NULL,
       `Country` varchar(2) DEFAULT NULL,
       `LScore2` int(11) DEFAULT NULL,
       `MarketCAPUSD` bigint(20) DEFAULT NULL,
       PRIMARY KEY (`RecNum`)
     ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

     -- ----------------------------
     -- Records of levermann
     -- ----------------------------
     INSERT INTO `levermann` VALUES ('8099', '2018-05-23', 'ANDR.VI', 'VI', '-9', '5109518494');
     INSERT INTO `levermann` VALUES ('8100', '2018-05-23', 'BWO.VI', 'VI', '-7', '4241189324');
     INSERT INTO `levermann` VALUES ('8101', '2018-05-23', 'CAI.VI', 'VI', '-7', '3222135865');
     INSERT INTO `levermann` VALUES ('8102', '2018-05-09', 'CWI.VI', 'VI', '-8', null);
     INSERT INTO `levermann` VALUES ('8103', '2018-05-23', 'EBS.VI', 'VI', '-7', '18317742129');
     INSERT INTO `levermann` VALUES ('8104', '2018-05-23', 'FLU.VI', 'VI', '-8', '3176359049');
     INSERT INTO `levermann` VALUES ('8105', '2018-05-23', 'IIA.VI', 'VI', '-8', '2767477473');
     INSERT INTO `levermann` VALUES ('8106', '2018-05-23', 'LNZ.VI', 'VI', '-9', '3027507195');

Выходными данными должна быть таблица, в которой каждый STOCKCODE (например, ANDR.VI) из этих 8 должен быть столбцом с одним выбираемым значением измерения (например, LScore2), сгруппированным по tradedate (= строка).

snipset of a demo output

Я нашел это Exmapl в MYSQL , но я не понимаю его полностью. Более того, я сделал это:

    SELECT
    tradedate, 
    GROUP_CONCAT(stock_short) as STOCKCODE
    FROM
    levermann
    GROUP BY
    Tradedate;

Но здесь биржевые коды находятся в одной ячейке, а не в заголовке. Вот изображение примера желаемого результата. Общее количество столбцов составляет около 4000 (максимальное количество столбцов в таблице не превышает 4096). И сделки (= строки) составляют около 350 дней / лет в течение 2 лет в общей сложности.

Понятно, что столбцы должны создаваться динамически и не могут быть жестко закодированы операторами AS.

Есть ли решение этого трудного вопроса? СПАСИБО много.

Обновление: Я думаю о динамически работающем утверждении, подобном этому.

    SET @sql = NULL;

    SELECT GROUP_CONCAT(concat(LScore2,' AS `LScore_',Stock_Short,'`')) into 
    @sql from levermann;

    SET @sql = CONCAT('SELECT tradedate, ', @sql, '
              FROM levermann 
               GROUP BY tradedate');

     PREPARE stmt FROM @sql;
     EXECUTE stmt;
     DEALLOCATE PREPARE stmt;

Но я не знаю, как я могу создать строку:

LScore AS LScore_ANDR.VI, LScore AS LScore_BWO.VI, ...

Я действительно сомневаюсь, но в MySQL это может быть сделано каким-то образом. Конечно, я тоже могу сделать скрипт php. Но я хотел бы узнать, как это делается в MySQL.

Обновление 2: я думаю, что смогу это сделать. Я не совсем уверен, правильно ли это, но он создается динамически. В MySQL

Ответы [ 3 ]

1 голос
/ 29 марта 2019

Я думаю, что у меня есть:

SET SESSION group_concat_max_len = @@max_allowed_packet;
SET @sql = NULL;

SELECT GROUP_CONCAT(concat('MAX(CASE Stock_Short WHEN \'',Stock_Short,'\'   THEN \'',LScore2,'\' END) AS `LScore_',Stock_Short,'`')) into @sql from levermanndemo where country = 'VI';

SET @sql = CONCAT('SELECT tradedate, ', @sql, '
              FROM levermanndemo  
               GROUP BY tradedate');


PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

ВЫХОД:

OUTPUT_ALL_OK

Обновление: К сожалению, это вызывает беспокойство, еслитаблица выглядит следующим образом.

ONE STOCK has 2 different Scores on 2 different Tradedates

Я попробовал это решение:

    SET SESSION group_concat_max_len = @@max_allowed_packet;
    SET @sql = NULL;

    SELECT  GROUP_CONCAT( DISTINCT concat('MAX(CASE WHEN p.Stock_Short = 
    \'',f.Stock_Short,'\' AND `Tradedate` = \'', f.tradedate,'\'  THEN 
    \'',f.LScore2,'\' ELSE NULL END) AS   `LScore_',f.Stock_Short,'`')) 
    into @sql from  levermanndemo f ;

    SET @sql = CONCAT('SELECT p.tradedate, ', @sql, ' FROM levermanndemo p 
    GROUP BY p.tradedate');
    #SELECT @sql; 

    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

Вывод не желателен - и неверен.Теперь есть 2 столбца с одинаковым STOCK (BWO.VI и BWO.VI1), я хотел бы объединить эти два столбца вместе.Но как это сделать?

wrong output

0 голосов
/ 30 марта 2019

Если список StockCodes фиксирован, можно ли не просто исправить столбцы новой таблицы, а затем отфильтровать данные в исходной таблице для копирования в новую таблицу?

По крайней мере, это будетпроцесс, когда вы делаете это вручную в Excel, например.

0 голосов
/ 29 марта 2019

В SQL вы не можете написать любой запрос, который динамически расширяет столбцы на основе значений данных, которые он находит, как только начинает читать данные. Все столбцы должны быть зафиксированы в списке выбора запроса во время его подготовки - за до он читает любые данные.

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

Вы можете решить эту проблему, выполнив два запроса: один, чтобы получить все различные значения запасов:

SELECT DISTINCT Stock_Short FROM levermann

Затем, основываясь на этом результате, отформатируйте более длинный SQL-запрос с выражением on для каждой стоимости акций. Начните с нужного вам столбца, который не является одним из динамических столбцов, связанных с акциями:

SELECT Tradedate,

Затем для каждой строки в результате первого запроса добавьте столбец, например:

MAX(CASE Stock_Short WHEN <value> THEN LScore2 END) AS <alias>,

Затем, наконец, добавьте конец запроса:

FROM levermann
GROUP BY Tradedate;

Моя рекомендация, поскольку у вас есть 4000 различных значений запасов, заключается в том, что вы должны просто извлечь данные из базы данных как есть и использовать код приложения для представления сводного дисплея. То есть зациклите результат запроса SQL на всех 4000 строках (не на столбцах) и разместите его в объект в пространстве приложения. Затем отформатируйте этот объект так, как вы хотите для отображения.

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