mysql - 具有大量动态列的 Mysql 中的数据透视表

标签 mysql pivot

我在 MySQL 中制作 PIVOT 表时遇到问题。我有下表。 (这是一个简化的演示表。真实的有 4000 只股票,用于 f.e 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');

输出应该是一个表格,其中这 8 个中的每个 STOCKCODE(例如 ANDR.VI)应该是一个列,其中包含一个按交易日期(= 行)分组的可选测量值(例如 LScore2)。

snipset of a demo output

我找到了这个Exmapl in 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 作为 LScore_ANDR.VI,LScore 作为 LScore_BWO.VI,...

我真的很怀疑,但它可能会在 MySQL 中以某种方式完成。 当然我也可以制作一个 php 脚本。但我想了解它是如何在 MySQL 中完成的。

更新 2:我想我可以做到。我不太确定它是否正确,但它是动态创建的。在 MySQL 中

最佳答案

我想我明白了:

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

关于mysql - 具有大量动态列的 Mysql 中的数据透视表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55406626/

相关文章:

sql - 将连接表的列旋转为行

mysql - Zend_Db : How to get the number of rows from a table?

mysql - 使用 mysqldump 备份带有 GEOMETRY 列的表?

mysql - MariaDB 相关子查询中 DateTimes 的截断

php - 如何定期更新MySQL中的数据?

MySQL 将行转为动态数量的列

r - pivot_longer 成多列

php - 在新窗口中打开 index.php?id=2

sql - SQL PIVOT可以做这样的转换吗?

c++ - 3 的中位数,使用迭代器进行快速排序