我试图在Oracle中使用LAG功能来查找捐赠者之前的注册值。
要查看我的数据,我从这个查询开始查找特定捐赠者的所有注册:
select registration_id, registration_date from registration r where r.person_id=52503290 order by r.registration_date desc;
然后我使用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
函数置于主查询中以获取先前的值,但由于某种原因,前一个值返回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;
以下是结果集:
有关我在这里缺少什么的建议吗?或者为什么这个查询没有返回预期的值?
基于@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秒:
我的原始查询(在添加LAG
功能之前)花了大约2秒钟来撤回大约2100条记录。但它只是一个带有几个JOINS的SELECT和WHERE子句中的一个项目。
根据记录计数,Person拥有近550万条记录,而且注册记录有910万条记录。
答案 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;