Mysql中的Pivot表具有许多动态列

Mysql中的Pivot表具有许多动态列,mysql,pivot,Mysql,Pivot,我在MySQL中创建数据透视表时遇到问题。我有下表。这是一个简化的演示表。真正的一个有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, `Cou

我在MySQL中创建数据透视表时遇到问题。我有下表。这是一个简化的演示表。真正的一个有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个股票代码f.e.和R.VI应为一列,带有一个可选测量值f.e.LScore2,按tradedate=行分组

我发现了这一点,但我并不完全理解。我已经做了更多:

    SELECT
    tradedate, 
    GROUP_CONCAT(stock_short) as STOCKCODE
    FROM
    levermann
    GROUP BY
    Tradedate;
但是这里的股票代码在一个单元格中,而不是在标题中。 以下是所需输出示例的图像。总列数约为4000列,表中的最大列数不超过4096列。tradedates=行总共2年约为350天/年

很明显,列应该动态创建,不能由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_和r.VI,LScore作为LScore_BWO.VI

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


更新2:我想我能做到。我不确定它是否正确,但它是动态创建的。在SQL中的MySQL中,一旦开始读取数据,就不能编写任何根据找到的数据值动态扩展列的查询。在准备查询时(在查询读取任何数据之前),必须固定查询的选择列表中的所有列

这意味着您必须知道所有不同的值,并且需要为要包含在透视中的每个值生成一个包含一列的选择列表

您可以通过执行两个查询来解决此问题:一个是获取所有不同的股票值:

SELECT DISTINCT Stock_Short FROM levermann
然后根据该结果,为每个股票值格式化一个带on表达式的Loooong SQL查询。从您知道需要的列开始,该列不是与动态股票相关的列之一:

SELECT Tradedate,
然后,对于firs查询结果中的每一行,添加一列,如:

MAX(CASE Stock_Short WHEN <value> THEN LScore2 END) AS <alias>,
我的建议是,因为您有4000个不同的股票价值,所以您应该按原样从数据库中获取数据,并使用应用程序代码显示数据透视。也就是说,循环SQL查询的结果(所有4000行而不是列),并将其排列到应用程序空间中的一个对象中。然后按您想要的方式格式化该对象以供显示。

我想我已经得到了它:

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;
输出:

更新:不幸的是,如果表看起来像这样,它会让troubel感到不安

我尝试了这个解决方案:

    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;
输出不理想,而且错误。现在有两列具有相同的BWO.VI和BWO.VI1,我想将这两列合并在一起。但如何做到这一点呢


如果股票代码列表是固定的,那么不能简单地固定新表的列,然后过滤原始表中的数据以复制到新表中吗


至少这是在Excel中手动执行的过程。

非常感谢,也许你是对的,我想我可以创建一个dyn sql语句,就像上面的更新一样。我想我已经做到了:非常接近,但当值变大时仍然会失败。。我还建议使用SET SESSION group\u concat\u max\u len=@@max\u allowed\u packet;在运行此查询之前,表示结果被截断为group_concat_max_len系统变量给定的最大长度,该系统变量的默认值为1024。。一般情况下,在使用组\u CONCAT时,请配置组\u CONCAT\u max\u lensetting@RaymondNijland非常感谢,我真的在想,找不到所有栏目都不起作用的原因。此外,我在参加合适的约会时遇到了麻烦。所有日期的行都相同。你知道为什么吗?我怎样才能使左外连接正确呢?数据透视需要更多的通用语法,格式为off MAXCASE Stock_Short,然后LScore2结束为,不确定你在这里做什么或你在说什么。@RaymondNijland我真的不明白这句话。为什么是MAX?我只想按原样使用LScore2。请你解释一下好吗?Thanks@RaymondNijland我能做到,看更新的便条谢谢你们!谢谢,但这应该是自动完成的。我现在已经成功地用php完成了。
    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;