将 MAX() KEEP (DENSE_RANK LAST ORDER BY TIMESTAMP) OVER( PARTITION BY) 转换为 MySql

Convert MAX() KEEP (DENSE_RANK LAST ORDER BY TIMESTAMP ) OVER( PARTITION BY) to MySql

我需要将多个视图从 Oracle 转换为 mySql。除了一个,我成功地完成了所有转换:

CREATE or replace VIEW BPMS_POC_ACC_LATEST_ANSWERS_V (PROCESS_ID, QUESTION_ID, QUESTION_GRP, ANSWER, VERSION, TYPE, AUTHOR, TIMESTAMP, PKEY) AS
WITH t2 AS
(
SELECT BPMS_POC_ACC_ANSWER.*, MAX(TIMESTAMP) KEEP (DENSE_RANK LAST ORDER BY TIMESTAMP ) OVER( PARTITION BY QUESTION_GRP, QUESTION_ID , PROCESS_ID ) 
            AS highest
  FROM BPMS_POC_ACC_ANSWER

)
SELECT PROCESS_ID, QUESTION_ID, QUESTION_GRP, ANSWER, VERSION, TYPE, AUTHOR, TIMESTAMP, CONCAT(CONCAT(PROCESS_ID,QUESTION_GRP),QUESTION_ID) AS PKEY
  FROM t2
 WHERE highest = TIMESTAMP 

我认为问题在于:MAX() KEEP (DENSE_RANK LAST ORDER BY TIMESTAMP) OVER( PARTITION BY)

有人知道转换它的简单方法吗?

就此而言,此查询为您提供了每个 (QUESTION_GRP, QUESTION_ID , PROCESS_ID) 元组的最新记录,按 TIMESTAMP 排序。

您可以简单地为此使用相关子查询:

CREATE or replace VIEW BPMS_POC_ACC_LATEST_ANSWERS_V 
    (PROCESS_ID, QUESTION_ID, QUESTION_GRP, ANSWER, VERSION, TYPE, AUTHOR, TIMESTAMP, PKEY) AS
SELECT 
    PROCESS_ID, 
    QUESTION_ID, 
    QUESTION_GRP, 
    ANSWER, 
    VERSION, 
    TYPE, 
    AUTHOR, 
    TIMESTAMP, 
    CONCAT(CONCAT(PROCESS_ID,QUESTION_GRP),QUESTION_ID) AS PKEY
FROM BPMS_POC_ACC_ANSWER a
WHERE a.TIMESTAMP = (
    SELECT MAX(a1.TIMESTAMP)
    FROM BPMS_POC_ACC_ANSWER a1
    WHERE 
        a1.QUESTION_GRP = a.QUESTION_GRP
        AND a1.QUESTION_ID = a.QUESTION_ID
        AND a1.PROCESS_ID = a.PROCESS_ID
)

这种方法的好处是它适用于 MySQL 的所有版本,即使在不支持 window 函数的 5.x 版本中也是如此。

在 MySQL 8.0 中,您还可以使用 RANK():

CREATE or replace VIEW BPMS_POC_ACC_LATEST_ANSWERS_V 
    (PROCESS_ID, QUESTION_ID, QUESTION_GRP, ANSWER, VERSION, TYPE, AUTHOR, TIMESTAMP, PKEY) AS
SELECT 
    PROCESS_ID, 
    QUESTION_ID, 
    QUESTION_GRP, 
    ANSWER, 
    VERSION, 
    TYPE, 
    AUTHOR, 
    TIMESTAMP, 
    CONCAT(CONCAT(PROCESS_ID,QUESTION_GRP),QUESTION_ID) AS PKEY
FROM (
    SELECT 
        a.*,
        RANK() OVER(PARTITION BY QUESTION_GRP, QUESTION_ID, PROCESS_ID ORDER BY TIMESTAMP DESC) rn
    FROM BPMS_POC_ACC_ANSWER a
) a
WHERE rn = 1

MAX(TIMESTAMP) KEEP (DENSE_RANK LAST ORDER BY TIMESTAMP) 没有意义。它说:给我最大的时间戳,如果有联系,给我他们的最大值。你也可以只写 MAX(TIMESTAMP).

CONCAT(CONCAT(process_id, question_grp), question_id) 也很奇怪。这只是 process_id || question_grp || question_id.

所以,我们实际上有

WITH t2 AS
(
  SELECT 
    bpms_poc_acc_answer.*,
    MAX(timestamp) OVER (PARTITION BY question_grp, question_id, process_id) AS highest
  FROM bpms_poc_acc_answer
)
SELECT
  process_id, question_id, question_grp, answer, version, type, author, timestamp,
  process_id || question_grp || question_id AS pkey
FROM t2
WHERE highest = timestamp;

这是标准的 SQL,但字符串连接可能依赖于空字符串和 null 在 Oracle 中相同。在 MySQL 中,您可以为此使用 CONCAT_WS

WITH t2 AS
(
  SELECT 
    bpms_poc_acc_answer.*,
    MAX(timestamp) OVER (PARTITION BY question_grp, question_id, process_id) AS highest
  FROM bpms_poc_acc_answer
)
SELECT
  process_id, question_id, question_grp, answer, version, type, author, timestamp,
  CONCAT_WS('', process_id || question_grp || question_id) AS pkey
FROM t2
WHERE highest = timestamp;

这应该从 MySQL 8 开始工作。早期版本没有 CTE 和 window 函数,您可以改为:

SELECT
  process_id, question_id, question_grp, answer, version, type, author, timestamp,
  CONCAT_WS('', process_id || question_grp || question_id) AS pkey
FROM bpms_poc_acc_answer
WHERE (question_grp, question_id, process_id, timestamp) IN
(
  SELECT question_grp, question_id, process_id, MAX(timestamp)
  FROM bpms_poc_acc_answer
  GROUP BY question_grp, question_id, process_id
);