使用LAG在Oracle中查找以前的值

时间:2015-06-10 19:05:02

标签: oracle plsql

我试图在Oracle中使用LAG功能来查找捐赠者之前的注册值。

要查看我的数据,我从这个查询开始查找特定捐赠者的所有注册:

select registration_id, registration_date from registration r where r.person_id=52503290 order by r.registration_date desc;

Registrations

然后我使用LAG函数返回先前的值以及最近的值:

select registration_id as reg_id, registration_date as reg_date, lag(registration_date,1) over (order by registration_date) as prev_reg_date from registration where person_id=52503290 order by registration_date desc;

结果如预期:

LAG Function

所以我认为我应该将LAG函数置于主查询中以获取先前的值,但由于某种原因,前一个值返回NULL或根本没有值。

SELECT P.Person_Id AS Person_ID, R.Registration_Date AS Drive_Date, LAG(R.Registration_Date,1) OVER (ORDER BY R.REGISTRATION_DATE) AS Previous_Drive_Date, P.Abo AS Blood_Type, DT.Description AS Donation_Type FROM Person P JOIN Registration R ON P.Person_Id = R.Person_Id AND P.First_Name <> 'Pooled' AND P.First_Name <> 'IMPORT' LEFT OUTER JOIN Drives DR ON R.Drive_Id = DR.Drive_Id AND DR.Group_Id <> 24999 LEFT OUTER JOIN Branches B ON R.Branch_Id = B.Branch_Id LEFT OUTER JOIN Donor_Group DG on DR.Group_Id = DG.Group_Id LEFT OUTER JOIN Donation_Type DT ON R.Donation_Type_Id = DT.DONATION_TYPE_ID WHERE TRUNC(R.Registration_Date) = TRUNC(SYSDATE)-1 AND R.Person_Id=52503290 ORDER BY R.Registration_Date DESC;

以下是结果集:

Main Query

有关我在这里缺少什么的建议吗?或者为什么这个查询没有返回预期的值?

基于@Alex Poole的建议,我将查询更改为:

SELECT * FROM (
SELECT
       P.Person_Id AS Person_ID,
       R.Registration_Date AS Drive_Date,
       LAG(R.Registration_Date,1) OVER (partition by p.person_id ORDER BY r.registration_date) AS Previous_Drive_Date,
       P.Abo AS Blood_Type,
       DT.Description AS Donation_Type
FROM
       Person P
       JOIN Registration R ON P.Person_Id = R.Person_Id AND P.First_Name <> 'Pooled' AND P.First_Name <> 'IMPORT'
       LEFT OUTER JOIN Drives DR ON R.Drive_Id = DR.Drive_Id AND DR.Group_Id <> 24999
       LEFT OUTER JOIN Branches B ON R.Branch_Id = B.Branch_Id
       LEFT OUTER JOIN Donor_Group DG on DR.Group_Id = DG.Group_Id
       LEFT OUTER JOIN Donation_Type DT ON R.Donation_Type_Id = DT.DONATION_TYPE_ID
--WHERE R.Person_Id=52503290
)
WHERE TRUNC(Drive_Date) = TRUNC(SYSDATE)-1
ORDER BY Drive_Date DESC;

拉回前30行需要大约85秒:

Query Results

我的原始查询(在添加LAG功能之前)花了大约2秒钟来撤回大约2100条记录。但它只是一个带有几个JOINS的SELECT和WHERE子句中的一个项目。

根据记录计数,Person拥有近550万条记录,而且注册记录有910万条记录。

1 个答案:

答案 0 :(得分:1)

延迟仅应用于与where子句过滤器匹配的行中,因此如果也是昨天,您只会看到之前的值。

您可以在子查询中应用滞后,然后在外部查询中进行过滤:

SELECT * FROM (
    SELECT
           P.Person_Id AS Person_ID,
           R.Registration_Date AS Drive_Date,
           LAG(R.Registration_Date,1) OVER (ORDER BY R.REGISTRATION_DATE) AS Previous_Drive_Date,
           P.Abo AS Blood_Type,
           DT.Description AS Donation_Type
    FROM
           Person P
           JOIN Registration R ON P.Person_Id = R.Person_Id AND P.First_Name <> 'Pooled' AND P.First_Name <> 'IMPORT'
           LEFT OUTER JOIN Drives DR ON R.Drive_Id = DR.Drive_Id AND DR.Group_Id <> 24999
           LEFT OUTER JOIN Branches B ON R.Branch_Id = B.Branch_Id
           LEFT OUTER JOIN Donor_Group DG on DR.Group_Id = DG.Group_Id
           LEFT OUTER JOIN Donation_Type DT ON R.Donation_Type_Id = DT.DONATION_TYPE_ID
    WHERE R.Person_Id=52503290
)
WHERE TRUNC(Drive_Date) = TRUNC(SYSDATE)-1
ORDER BY Drive_Date DESC;