基于日期的 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 中仅加载最近 5 天内修改的项目的 SQL 性能?
Oracle SQL - 从最近三个 GRN 日期获取项目的最高 (Max) 价格 (Order By)