【问题标题】:MySQL pivot table in 1 to n relationship1 到 n 关系中的 MySQL 数据透视表
【发布时间】:2016-08-15 07:18:43
【问题描述】:

我有这样的数据 表master_item

+-------+----------+ |item_id|item_name| +-------+----------+ | 001 |车A | | 002 |车B | +-------+----------+

和关系到表进程

+-------+--------+ |proc_id|proc_seq| +-------+--------+ | 001 | 1 | | 001 | 2 | | 001 | 3 | | 001 | 4 | | 001 | 5 | | 002 | 1 | | 002 | 2 | | 002 | 3 | +-------+--------+

当我选择 item_id = 001 时,我想要这样的结果

+-------+---------+-----+------+-----+-----+-----+- -+-----+ |item_id|item_name|proc1|proc2|proc3|proc4|proc5|proc6|proc7| +-------+---------+-----+------+-----+-----+-----+- -+-----+ | 001 |车A | 1 | 2 | 3 | 4 | 5 | | | +-------+---------+-----+------+-----+-----+-----+- -+-----+

产生这个结果的查询是什么?

【问题讨论】:

  • 采用简单查询,而不是通过数据透视表查询。并在应用程序级别完成其余的工作

标签: mysql join


【解决方案1】:

问题在于PIVOT TABLE类别。

在这里您可以通过下面给出的查询来完成您的结果:

SET @sql := '';
SELECT 
CONCAT('SELECT 
MI.item_id,
MI.item_name,',
GROUP_CONCAT('MAX(CASE WHEN P.proc_seq =', P.proc_seq ,' THEN P.proc_seq END) AS ', 'proc',P.proc_seq,' '),
'FROM master_item MI
INNER JOIN process P ON MI.item_id = P.proc_id
WHERE MI.item_id = 1
GROUP BY P.proc_id') INTO @sql
FROM master_item MI
INNER JOIN process P ON MI.item_id = P.proc_id
WHERE item_id = 1
GROUP BY P.proc_id;


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

WORKING DEMO

但就像我说的,最好在应用程序逻辑中做这种工作。否则单独通过 MySQL 做起来太麻烦了。

编辑:

为了得到每个item_id的结果

SET @sql := '';
SELECT 
CONCAT('SELECT 
MI.item_id,
MI.item_name,',
GROUP_CONCAT('MAX(CASE WHEN P.proc_seq =', P.proc_seq ,' THEN P.proc_seq END) AS ', 'proc',P.proc_seq,' '),
'FROM master_item MI
INNER JOIN process P ON MI.item_id = P.proc_id
GROUP BY P.proc_id') INTO @sql
FROM master_item MI
INNER JOIN process P ON MI.item_id = P.proc_id

WHERE
    item_id = (
        SELECT
            maxProcId.proc_id
        FROM
            (
                SELECT
                    proc_id,
                    COUNT(proc_seq) total
                FROM process
                GROUP BY proc_id
                ORDER BY total DESC
                LIMIT 1
            ) AS maxProcId
    )
GROUP BY
    P.proc_id;


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

Demonstrated here

【讨论】:

  • 很好,但名称和 ID 始终为 1,CAR A 和进程是随机的
  • 您不是只想要item_id = 1 的结果吗?
  • 请在编辑部分运行更新后的查询。我在那里做了改变。
【解决方案2】:

使用Group_concat,然后将数据拆分到单独的列即可

SELECT t1.*,
      SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(t2.proc_seq), ',', 1), ',', -1) AS proc1, 
      SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(t2.proc_seq), ',', 2), ',', -1) AS proc2, 
      SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(t2.proc_seq), ',', 3), ',', -1) AS proc3, 
      SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(t2.proc_seq), ',', 4), ',', -1) AS proc4, 
      SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(t2.proc_seq), ',', 5), ',', -1) AS proc5
FROM tt1 t1
LEFT JOIN tt2 t2 ON t1.item_id=t2.proc_id

【讨论】:

  • thx @ashkufaraz 为您的回复,但我希望结果按照流程显示在每一列中,而不是在列过程中制作一个
  • 我更新了我的答案,你可以用 sub string_index 来做
  • 很好,但是当 seq 是随机的时过程不准确..必须先索引
猜你喜欢
  • 2017-10-03
  • 2017-07-22
  • 2014-09-12
  • 1970-01-01
  • 1970-01-01
  • 2014-09-29
  • 2014-08-26
  • 2021-01-19
  • 1970-01-01
相关资源
最近更新 更多