基于日期的 Oracle SQL 最近行

Posted

技术标签:

【中文标题】基于日期的 Oracle SQL 最近行【英文标题】:Oracle SQL Most Recent Row based on Date 【发布时间】:2018-11-25 17:06:09 【问题描述】:

我知道这个问题已经在论坛上被问过很多次了,我已经尝试了多种方法来获取我需要的东西,但总是有一些错误消息,所以我失去了尝试调试它的意愿。我在 Oracle Fusion 13C 中编写 SQL

我收到的消息是“值太多”,我很确定它来自我最后的 where 子句。没有最后一行的代码带回两行正确的数据,我只想带回一个,尽管根据“ACTION_DATE”列中哪一行具有最新日期,或者如果“SEQUENCE_NUM”中的最高数字失败柱子。

到目前为止我得到的代码是:

WITH
PERSON_DETAILS AS (SELECT DISTINCT
                    PERSON_ID AS PPNPERSONID,
                    FULL_NAME
                FROM
                    PER_PERSON_NAMES_F
                WHERE
                    TO_DATE(EFFECTIVE_END_DATE, 'yyyy/mm/dd') > TO_DATE(SYSDATE, 'yyyy/mm/dd')
                    AND NAME_TYPE = 'GLOBAL'

),

PERSON_ASSIGNMENT AS (SELECT DISTINCT
                        PD.*,
                        PAAM.PERSON_ID AS PAAMPERSONID,
                        PAAM.JOB_ID AS PAAMJOBID
                    FROM
                        PERSON_DETAILS PD,
                        PER_ALL_ASSIGNMENTS_M PAAM
                    WHERE
                        PD.PPNPERSONID = PAAM.PERSON_ID
                        AND TO_DATE(PAAM.EFFECTIVE_END_DATE, 'yyyy/mm/dd') > TO_DATE(SYSDATE, 'yyyy/mm/dd')

),

PERSON_JOB AS (SELECT DISTINCT
                PA.*,
                PJF.JOB_ID AS PJFJOBID,
                PJF.APPROVAL_AUTHORITY
            FROM
                PERSON_ASSIGNMENT PA,
                PER_JOBS_F PJF
            WHERE
                PA.PAAMJOBID = PJF.JOB_ID
                AND TO_DATE(PJF.EFFECTIVE_END_DATE, 'yyyy/mm/dd') > TO_DATE(SYSDATE, 'yyyy/mm/dd')



),

REQ_APPROVER_DETAIL AS (SELECT DISTINCT
                        PJ.*,
                        PAH.OBJECT_TYPE_CODE ,
                        PAH.SEQUENCE_NUM ,
                        PAH.ACTION_CODE ,
                        PAH.ACTION_DATE ,
                        PAH.PERFORMER_ID,
                        PAH.OBJECT_ID AS PAHOBJECTID
                    FROM
                        FUSION.PO_ACTION_HISTORY PAH,
                        PERSON_JOB PJ
                    WHERE
                        PAH.PERFORMER_ID = PJ.PPNPERSONID
                        AND ACTION_CODE = 'APPROVE'

),
REQ_DETAIL AS (SELECT DISTINCT
                RAD.*,
                RHA.requisition_number AS Req_Number,
                RHA.requisition_header_id RHAREQHEADID

            FROM
                REQ_APPROVER_DETAIL RAD,
                FUSION.POR_REQUISITION_HEADERS_ALL RHA
            WHERE
                RAD.PAHOBJECTID = RHA.requisition_header_id

),

REQ_LINE_DETAIL AS (SELECT DISTINCT
                    RD.*,
                    SUM(rla.unit_price*rla.quantity) AS QUANTITY_AMOUNT,
                    SUM(rla.amount) AS AMOUNT_ORDERED
                FROM
                    POR_REQUISITION_LINES_ALL RLA,
                    REQ_DETAIL RD
                WHERE
                    RD.RHAREQHEADID = RLA.requisition_header_id
                GROUP BY
                    RHAREQHEADID,
                    Req_Number,
                    OBJECT_TYPE_CODE,
                    SEQUENCE_NUM,
                    ACTION_CODE,
                    ACTION_DATE,
                    PERFORMER_ID,
                    PAHOBJECTID,
                    PJFJOBID,
                    APPROVAL_AUTHORITY,
                    PPNPERSONID,
                    FULL_NAME,
                    PAAMPERSONID,
                    PAAMJOBID



),

REQ_TOTAL_AMOUNT AS (SELECT DISTINCT
                    RLD.*,
                    CASE WHEN RLD.AMOUNT_ORDERED IS NULL THEN 
RLD.QUANTITY_AMOUNT
                        ELSE RLD.AMOUNT_ORDERED
                            END AS REQ_AMOUNT_TOTAL
                    FROM
                        REQ_LINE_DETAIL RLD
)

SELECT 
Req_Number,
FULL_NAME,
SEQUENCE_NUM,
REQ_AMOUNT_TOTAL,
--OBJECT_TYPE_CODE,
ACTION_DATE,
--ACTION_CODE
--APPROVAL_AUTHORITY


FROM REQ_TOTAL_AMOUNT

--WHERE PPNPERSONID = '300000008160059'
WHERE REQ_NUMBER = '702387'
AND ACTION_DATE = (SELECT 
MAX(PAH.ACTION_DATE),PAH.PERFORMER_ID FROM FUSION.PO_ACTION_HISTORY PAH, PER_PERSON_NAMES_F PPN WHERE PAH.PERFORMER_ID = PPN.PERSON_ID)

感谢您提供的任何帮助。我已经将它调试到最后一个 SELECT 中的最后一个 WHERE 子句。如果我删除它/注释掉最后一行,它可以带回两行。目前我带回来的数据是:

REQ_Number|FULL_NAME|SEQUENCE_NUM|REQ_TOTAL_AMOUNT|ACTION_DATE
702387     Sam Jones    3          £19,000         2017-08-23T12:08:39.000+00:00
702387     Bill Baggins  4         £19,000         2017-08-23T13:55:55.000+00:00

我想只为 Bill Baggins 带回这一行,因为它是两行中最新执行的那一行,但如果不能在 Action_Date 上完成,那么 SEQUENCE_NUM 也会将其带回为 4 > 3等

任何帮助将不胜感激。再次抱歉,因为这个问题无疑已经被问过很多次了

问候,

马特

【问题讨论】:

谢谢马特。您提到的最后一个谓词看起来像是选择了两个东西:MAX(PAH.ACTION_DATE)PAH.PERFORMER_ID,但它用于与ACTION_DATE 的相等比较。 sql 引擎将无法将一项与两项进行比较。如果您丢弃PAH.PERFORMER_ID 并在最终子查询中仅使用MAX(PAH.ACTION_DATE) 会发生什么?最终的子查询可能无论如何都无法独立执行,因为 PERFORMER_ID 既不是聚合也不是分区键。 【参考方案1】:

是的,这是你的问题:

AND ACTION_DATE = (SELECT MAX(PAH.ACTION_DATE), PAH.PERFORMER_ID 
                     FROM FUSION.PO_ACTION_HISTORY PAH, PER_PERSON_NAMES_F PPN 
                    WHERE PAH.PERFORMER_ID = PPN.PERSON_ID)

您的子查询返回两列,MAX(PAH.ACTION_DATE)PAH.PERFORMER_ID,但您使用 =ACTION_DATE 进行检查。因此,您将一列与两列进行比较,这是行不通的。

你可以用(ACTION_DATE, <some other column>) = ... 做这样的事情,但我很确定这甚至不会解析,因为你在子查询中没有GROUP BY 子句。在任何情况下,该子查询必须只返回一行,否则您将得到“ORA-01427:子查询返回多行”。

我怀疑您的子查询不是您想要的,您想删除 pah.performer_id 并添加一个将其与主查询相关联的子句,也许是 AND PAH.PERFORMER_ID = REQ_TOTAL_AMOUNT.PPNPERSONID

【讨论】:

以上是关于基于日期的 Oracle SQL 最近行的主要内容,如果未能解决你的问题,请参考以下文章

尝试查找 Oracle SQL 中状态字段更改的最近日期

oracle sql 最近5个季度的最后一天

如何提高 Oracle 中仅加载最近 5 天内修改的项目的 SQL 性能?

Oracle SQL - 从最近三个 GRN 日期获取项目的最高 (Max) 价格 (Order By)

基于提示的 Oracle SQL 调优——对最近的版本有啥好处?

在Oracle中选择具有最近日期和时间的记录[重复]