简体   繁体   English

将 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

I need to convert several views from Oracle to mySql. I managed to convert all but one:我需要将多个视图从 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 

I believe the problem is in: MAX() KEEP (DENSE_RANK LAST ORDER BY TIMESTAMP ) OVER( PARTITION BY)我认为问题出在:MAX() KEEP (DENSE_RANK LAST ORDER BY TIMESTAMP) OVER( PARTITION BY)

Does anybody know an easy way to convert it?有人知道转换它的简单方法吗?

As far as concerns, this query gives you the latest record for each (QUESTION_GRP, QUESTION_ID, PROCESS_ID) tuple, ordered by TIMESTAMP .就关注而言,此查询为您提供每个(QUESTION_GRP, QUESTION_ID, PROCESS_ID)元组的最新记录,按TIMESTAMP排序。

You could simply use a correlated subquery for that:您可以简单地为此使用相关子查询:

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
)

The upside of this approach is that it will work on all versions of MySQL, even in versions 5.x, which do not support window functions.这种方法的好处是它适用于 MySQL 的所有版本,即使在不支持 window 函数的 5.x 版本中也是如此。

In MySQL 8.0, you could also use RANK() :在 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) makes no sense. MAX(TIMESTAMP) KEEP (DENSE_RANK LAST ORDER BY TIMESTAMP)没有意义。 It says: give me the maximum timestamp and in case of ties give me their maximum.它说:给我最大的时间戳,如果有联系,给我他们的最大值。 You can just as well just write MAX(TIMESTAMP) .您也可以只写MAX(TIMESTAMP)

CONCAT(CONCAT(process_id, question_grp), question_id) is also weird. CONCAT(CONCAT(process_id, question_grp), question_id)也很奇怪。 This is just process_id || question_grp || question_id这只是process_id || question_grp || question_id process_id || question_grp || question_id process_id || question_grp || question_id . process_id || question_grp || question_id

So, we actually have所以,我们实际上有

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;

This is standard SQL, but the string concatenation may rely on the empty string and null being the same in Oracle. In MySQL you can use CONCAT_WS for this:这是标准的 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;

This should work as of MySQL 8. Earlier versions don't feature CTEs and window functions and you would write instead:这应该从 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
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM