使用 pivot 连接表使用 Mysql 8 版本

Using pivot to join tables using Mysql 8 version

我已经将这两个 table t1t2 存储在一个数据库 MySql 版本 8.0.17

重要的是 table t2 可以包含数千行不同的单元代码(字段 sUn)...

相反,table t1 仅包含每个单元的方法和代码(字段 TABLE_NAME

-- ----------------------------
-- Table structure for t1
-- ----------------------------
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1`  (
  `TABLE_NAME` varchar(255) DEFAULT NULL,
  `tDDMMYYHHMMSS` datetime DEFAULT NULL,
  `sID` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`sID`) USING BTREE,
  UNIQUE INDEX `TABLE_NAME`(`TABLE_NAME`) USING BTREE
) ENGINE = InnoDB;

-- ----------------------------
-- Records of t1
-- ----------------------------
INSERT INTO `t1` VALUES ('100', '2021-04-09 12:44:30', 1);
INSERT INTO `t1` VALUES ('11c', '2021-04-09 12:44:30', 2);
INSERT INTO `t1` VALUES ('11f', '2021-04-09 12:44:30', 3);
INSERT INTO `t1` VALUES ('12a', '2021-04-09 12:44:30', 4);
INSERT INTO `t1` VALUES ('12h', '2021-04-09 12:44:30', 5);

-- ----------------------------
-- Table structure for t2
-- ----------------------------
DROP TABLE IF EXISTS `t2`;
CREATE TABLE `t2`  (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `sUn` varchar(255) DEFAULT NULL,
  `sUnName` varchar(255) DEFAULT NULL,
  `sContents` longtext NULL,
  PRIMARY KEY (`sid`) USING BTREE
) ENGINE = InnoDB;

-- ----------------------------
-- Records of t2
-- ----------------------------
INSERT INTO `t2` VALUES (1, '100', 'NOR', 'Ipsa sua melior fama.');
INSERT INTO `t2` VALUES (2, '100', 'NOR', 'In toto.');
INSERT INTO `t2` VALUES (3, '100', 'NOR', 'Homines, nihil agendo.');
INSERT INTO `t2` VALUES (4, '11C', 'SAR', 'Habere non haberi.');
INSERT INTO `t2` VALUES (5, '11C', 'SAR', 'Vivere est cogitare.');
INSERT INTO `t2` VALUES (6, '11C', 'SAR', 'Urbi et Orbi.');
INSERT INTO `t2` VALUES (7, '11F', 'SAD', 'Inter sidera versor.');
INSERT INTO `t2` VALUES (8, '11F', 'SAD', 'Una tantum.');
INSERT INTO `t2` VALUES (9, '11F', 'SAD', 'Carthago delenda est.');
INSERT INTO `t2` VALUES (10, '12A', 'RIV', 'Status quo.');
INSERT INTO `t2` VALUES (11, '12A', 'RIV', 'Aut aut.');
INSERT INTO `t2` VALUES (12, '12A', 'RIV', 'Condicio sine qua non.\r\n');
INSERT INTO `t2` VALUES (13, '12H', 'CUN', 'Ubi maior minor cessat.');
INSERT INTO `t2` VALUES (14, '12H', 'CUN', 'Carpe diem.');
INSERT INTO `t2` VALUES (15, '12H', 'CUN', 'Venni, vidi, vinsi.');

我试过-没有成功- 一个查询枢轴连接这两个tables return

+------------------------+----------------------+-----------------------+------------------------+-------------------------+
| NOR                    | SAR                  | SAD                   | RIV                    | CUN                     |
+------------------------+----------------------+-----------------------+------------------------+-------------------------+
| Ipsa sua melior fama.  | Habere non haberi.   | Inter sidera versor.  | Status quo.            | Ubi maior minor cessat. |
| In toto.               | Vivere est cogitare. | Una tantum.           | Aut aut.               | Carpe diem.             |
| Homines, nihil agendo. | Urbi et Orbi.        | Carthago delenda est. | Condicio sine qua non. | Venni, vidi, vinsi.     |
+------------------------+----------------------+-----------------------+------------------------+-------------------------+

我的以下查询有误

任何帮助将不胜感激...谢谢。

SELECT
    max(
    IF
    ( t.sUn = q.TABLE_NAME, t.sContents, NULL )) q.sUnName
FROM
    ( SELECT row_number() over ( PARTITION BY sUn ORDER BY sID ) AS rn, tcs.sUn, tcs.sContents FROM t2 AS tcs ) AS t    
    JOIN t1 q ON t.sUn = q.TABLE_NAME   
GROUP BY
    rn 
ORDER BY
    rn

1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.sUnName FROM ( SELECT row_number() over ( PARTITION BY sUn ORDER BY sID ) AS' at line 4 > Time: 0,001s

更新

新版本使用存储过程...

CREATE DEFINER=`root`@`localhost` PROCEDURE `pivot_20210409`()
BEGIN

SET SESSION group_concat_max_len = 1000000;

SELECT
  CONCAT('SELECT ',
    GROUP_CONCAT(
      CONCAT (
        "IF(`sUnName` = '",sUnName,'\',sContents,NULL) AS `',sUnName,'`'
      )
    ),
    ' FROM `t2`'
  ) INTO @SQL
FROM
 ( SELECT row_number() over ( PARTITION BY sUn ORDER BY sID ) AS rn, tcs.sUnName, tcs.sContents FROM t2 AS tcs
 GROUP BY tcs.sUnName
) AS data;

SELECT @SQL;

PREPARE stmt FROM @SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

END

return

+------------------------+----------------------+-----------------------+--------------------------+-------------------------+
| NOR                    | SAR                  | SAD                   | RIV                      | CUN                     |
+------------------------+----------------------+-----------------------+--------------------------+-------------------------+
| Ipsa sua melior fama.  | NULL                 | NULL                  | NULL                     | NULL                    |
| In toto.               | NULL                 | NULL                  | NULL                     | NULL                    |
| Homines, nihil agendo. | NULL                 | NULL                  | NULL                     | NULL                    |
| NULL                   | Habere non haberi.   | NULL                  | NULL                     | NULL                    |
| NULL                   | Vivere est cogitare. | NULL                  | NULL                     | NULL                    |
| NULL                   | Urbi et Orbi.        | NULL                  | NULL                     | NULL                    |
| NULL                   | NULL                 | Inter sidera versor.  | NULL                     | NULL                    |
| NULL                   | NULL                 | Una tantum.           | NULL                     | NULL                    |
| NULL                   | NULL                 | Carthago delenda est. | NULL                     | NULL                    |
| NULL                   | NULL                 | NULL                  | Status quo.              | NULL                    |
| NULL                   | NULL                 | NULL                  | Aut aut.                 | NULL                    |
| NULL                   | NULL                 | NULL                  | Condicio sine qua non.   | NULL                    |
| NULL                   | NULL                 | NULL                  | NULL                     | Ubi maior minor cessat. |
| NULL                   | NULL                 | NULL                  | NULL                     | Carpe diem.             |
| NULL                   | NULL                 | NULL                  | NULL                     | Venni, vidi, vinsi.     |
+------------------------+----------------------+-----------------------+--------------------------+-------------------------+

在 MySQL 中,遗憾的是,对于一堆任意命名的列,旋转很难做到。

这会得到你想要的结果(dbfiddle on db-fiddle.com,它提供 MySQL 8.)

WITH pivot AS (
  SELECT CASE WHEN SunName = 'NOR' THEN sContents ELSE NULL END NOR,
         CASE WHEN SunName = 'SAR' THEN sContents ELSE NULL END SAR,
         CASE WHEN SunName = 'SAD' THEN sContents ELSE NULL END SAD,
         CASE WHEN SunName = 'RIV' THEN sContents ELSE NULL END RIV,
         CASE WHEN SunName = 'CUN' THEN sContents ELSE NULL END CUN,
         sId
   FROM t2
), 
rownums AS (
  SELECT sId, row_number() OVER ( PARTITION BY sUn ORDER BY sID ) rn FROM t2
)
SELECT MAX(NOR) NOR, MAX(SAR) SAR, MAX(SAD) SAD, MAX(RIV) RIV, MAX(CUN) CUN
  FROM rownums
  JOIN pivot ON rownums.sId = pivot.sId
 GROUP BY rownums.rn

这个讨厌的子查询执行旋转操作。 (fiddle) 看看它是如何枚举列的?这就是您必须要做的事情

  SELECT CASE WHEN SunName = 'NOR' THEN sContents ELSE NULL END NOR,
         CASE WHEN SunName = 'SAR' THEN sContents ELSE NULL END SAR,
         CASE WHEN SunName = 'SAD' THEN sContents ELSE NULL END SAD,
         CASE WHEN SunName = 'RIV' THEN sContents ELSE NULL END RIV,
         CASE WHEN SunName = 'CUN' THEN sContents ELSE NULL END CUN,
         sId
   FROM t2

您可以编写一个使用字符串处理和MySQL's PREPARE statement to synthesize that sort of query. That's a reasonably big job. Advice here的存储过程。