如何将 table 从行展平到列

How to flatten a table from row to columns

我使用 MariaDB 10.2.21 我在其他地方没有看到这个确切的案例,因此我请求帮助。

我有一个历史记录 table,其中包含对 JIRA 问题中任何字段的每次更改的记录:

+----------+---------------+----------+-----------------+---------------------+
| IssueKey | OriginalValue | NewValue |      Field      |     ChangeDate      |
+----------+---------------+----------+-----------------+---------------------+
| HRSK-184 | (NULL)        |        2 | Risk Detection  | 2019-10-24 10:57:27 |
| HRSK-184 | (NULL)        |        2 | Risk Occurrence | 2019-10-24 10:57:27 |
| HRSK-184 | (NULL)        |        2 | Risk Severity   | 2019-10-24 10:57:27 |
| HRSK-184 | 2             |        4 | Risk Detection  | 2019-10-25 11:54:07 |
| HRSK-184 | 2             |        6 | Risk Detection  | 2019-10-25 11:54:07 |
| HRSK-184 | 2             |        3 | Risk Severity   | 2019-10-24 11:54:07 |
| HRSK-184 | 6             |        5 | Risk Detection  | 2019-10-26 09:11:01 |
+----------+---------------+----------+-----------------+---------------------+

每条记录都包含旧值和新值以及已更改的字段类型 ('Field'),当然还有该更改的相应时间戳。

我想查询时间点状态,为我提供 每个字段 'Risk Severity, Risk Occurrence and Risk Detection' 的最新值 的组合。

结果应该是这样的:

+----------+----------------+-------------------+------------------+----------------------+
| IssueKey | Risk Severity  |  Risk Occurrence  |  Risk Detection  |  ChangeDate          |
+----------+----------------+-------------------+------------------+----------------------+
| HRSK-184 | 3              |  2                |  5               |  2019-10-26 09:11:01 |
+----------+----------------+-------------------+------------------+----------------------+

有什么想法吗?我卡住了... 预先感谢您的努力!

你冷使用几个内联查询

select 
    IssueKey,
    (
        select t1.NewValue 
        from mytable t1 
        where t1.IssueKey = t.IssueKey and t1.Field = 'Risk Severity'
        order by ChangeDate desc limit 1
    ) `Risk Severity`,
    (
        select t1.NewValue 
        from mytable t1 
        where t1.IssueKey = t.IssueKey and t1.Field = 'Risk Occurrence'
        order by ChangeDate desc limit 1
    ) `Risk Occurrence`,
    (
        select t1.NewValue 
        from mytable t1 
        where t1.IssueKey = t.IssueKey and t1.Field = 'Risk Detection'
        order by ChangeDate desc limit 1
    ) `Risk Severity`,
    max(ChangeDate) ChangeDate
from mytable t
group by IssueKey

有了 (IssueKey, Field, ChangeDate, NewValue) 上的索引,这应该是一个有效的选择。

Demo on DB Fiddle:

IssueKey | Risk Severity | Risk Occurrence | Risk Severity | ChangeDate     
:------- | ------------: | --------------: | ------------: | :------------------
HRSK-184 |             3 |               2 |             5 | 2019-10-26 09:11:01

MariaDB 10.2 引入了一些 Window Functions 用于分析查询。

其中之一是 RANK() OVER (PARTITION BY ...ORDER BY...) 函数。

首先,你可以应用它,然后通过Conditional Aggregation :

SELECT IssueKey,
       MAX(CASE WHEN Field = 'Risk Severity'   THEN NewValue END ) AS RiskSeverity,
       MAX(CASE WHEN Field = 'Risk Occurrence' THEN NewValue END ) AS RiskOccurrence,
       MAX(CASE WHEN Field = 'Risk Detection'  THEN NewValue END ) AS RiskDetection,
       MAX(ChangeDate) AS ChangeDate
  FROM
  (
   SELECT RANK() OVER (PARTITION BY IssueKey, Field ORDER BY ChangeDate Desc) rnk,
          t.*
     FROM mytable t 
  ) t
  WHERE rnk = 1
  GROUP BY IssueKey;

IssueKey | RiskSeverity  | RiskOccurrence  | RiskDetection  | ChangeDate     
-------- + --------------+-----------------+----------------+--------------------
HRSK-184 |             3 |               2 |              5 | 2019-10-26 09:11:01

Demo