连接表将行列为连接到另一个表的列?

时间:2013-12-17 00:46:12

标签: mysql sql pivot

我有3个表 - 事物,defs和信息(可怕的名字,但为了简单而大大减少了!)

信息

CREATE TABLE `info` (
  `id` bigint(10) NOT NULL AUTO_INCREMENT,
  `thingid` bigint(10) NOT NULL DEFAULT '0',
  `defid` bigint(10) NOT NULL DEFAULT '0',
  `data` longtext NOT NULL,
  PRIMARY KEY (`id`),
  KEY `infodata_coufie_ix` (`thingid`,`defid`)
);

id   | thingid  | defid   | data
1    | 1        | 1       | 1
1    | 1        | 2       | 25
1    | 2        | 1       | 0
1    | 2        | 3       | yellow
1    | 3        | 1       | 0

DEFS

CREATE TABLE `defs` (
  `id` bigint(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `datatype` varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
);

id   | name    | datatype
1    | enabled | boolean
2    | size    | numeric
3    | colour  | string

CREATE TABLE `things` (
  `id` bigint(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
);

id    | name
1     | bill
2     | terry
3     | nancy

我希望能够显示“事物”的“defs”值,因此结果表/视图会像

thingid | name   | enabled   | size   | colour
1       | bill   | true      | 25     | null
2       | terry  | false     | null   | yellow
3       | nancy  | true      | null   | null

因此defs中的行将成为列标题;与thingid的列标题匹配的值将形成这些行的数据。

我很久以前就已经在SQL Server中做过这件事了,因为我的生活不记得怎么做了。我现在需要在MySql5中完成它。我一直在阅读http://www.artfulsoftware.com/infotree/queries.php以及各种SE文章,但我现在已经把自己搞得一团糟了,所以我实际上要问别人。

2 个答案:

答案 0 :(得分:2)

SELECT i.thingid, t.name,
       MAX(IF(d.name = "enabled", i.data, NULL)) enabled,
       MAX(IF(d.name = "size", i.data, NULL)) size,
       MAX(IF(d.name = "colour", i.data, NULL)) colour
FROM info i
JOIN defs d ON i.defid = d.id
JOIN things t ON i.thingid = t.id
GROUP BY i.thingid

DEMO

答案 1 :(得分:1)

我的解决方案:

CREATE TABLE info
    (`id` int, `thingid` int, `defid` int, `data` varchar(6))
;

INSERT INTO info
    (`id`, `thingid`, `defid`, `data`)
VALUES
    (1, 1, 1, '1'),
    (1, 1, 2, '25'),
    (1, 2, 1, '0'),
    (1, 2, 3, 'yellow'),
    (1, 3, 1, '0'),
    (1, 1, 5, 'bad'),
    (1, 1, 6, 2606),
    (1, 3, 4, 'banana')
;

CREATE TABLE defs
    (`id` int, `name` varchar(7), `datatype` varchar(7))
;

INSERT INTO defs
    (`id`, `name`, `datatype`)
VALUES
    (1, 'enabled', 'boolean'),
    (2, 'size', 'numeric'),
    (3, 'colour', 'string'),
    (4, 'flavour', 'thing'),
    (5, 'smell', 'essence'),
    (6, 'line', 'numeric')
;

CREATE TABLE things
    (`id` int, `name` varchar(5))
;

INSERT INTO things
    (`id`, `name`)
VALUES
    (1, 'bill'),
    (2, 'terry'),
    (3, 'nancy')
;

SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      ' MAX(IF(d.name = ''',
      d.name,
      ''', i.data, NULL)) AS ',
      d.name
    )
  ) INTO @sql
FROM info i join defs d on i.defid = d.id;
SET @sql = CONCAT('SELECT i.thingid, t.name, ',
           @sql, 
          ' FROM info i',
          ' JOIN defs d ON i.defid = d.id',
          ' JOIN things t ON i.thingid = t.id',
          ' GROUP BY i.thingid');
PREPARE statement FROM @sql;
EXECUTE statement;

请参阅小提琴:http://www.sqlfiddle.com/#!2/d481a/2

当您向defs添加更多列,并为这些记录添加后续数据info时,结果中会显示更多列,非匹配列中应为空值。