使用PLSQL寻找2种不同类型小计的建议。
我需要提取一个数据集,其中包括1)一个独特的人数,以及2)总学分数,作为随时间变化的总计。
原始数据:
这是交易数据 - 每次学生注册或课程时,都会插入包含日期,学生ID和学分(以及课程编号和一堆其他相关数据)的记录。每个学生每门课程一个记录。
STUDENT_ID CREDITS DATE
1 3 01-JAN-12
1 2 02-JAN-12
57 1 03-JAN-12
1 1 03-JAN-12
处理数据:
这是老板需要看到的 - 它将用于以后的趋势(例如,看看今年的01年1月如何衡量去年1月1日等)。
UniqueHeadcount SumCredits Date
1 3 01-JAN-12
1 5 02-JAN-12
2 7 03-JAN-12
对此的粗暴方法是编写一堆单独的SELECTS(每天一个),并将它们组合在一起。例如:
SELECT
COUNT(DISTINCT STUDENT_ID) as "UniqueHeadcount",
SUM(CREDIT_HR) as "SumCredits",
'01-JAN-12' as "DATE"
FROM
REGISTRATIONS
WHERE
TO_CHAR(DATE,'yyyymmdd') <= '20120101'
GROUP BY
'01-JAN-12'
UNION
SELECT
COUNT(DISTINCT STUDENT_ID) as "UniqueHeadcount",
SUM(CREDIT_HR) as "SumCredits",
'02-JAN-12' as "DATE"
FROM
REGISTRATIONS
WHERE
TO_CHAR(DATE,'yyyymmdd') <= '20120102'
GROUP BY
'02-JAN-12'
UNION
...
这是有效的 - 结果是准确的 - 但正如你所看到的 - 这远远不够优雅 - 如果你必须做365天,那么......它是一个野兽。必须有更好的方法来做到这一点。
到目前为止,在我的搜索中,我已经了解了我可以使用的'OVER'条款 - 就像这样:
SELECT
COUNT(DISTINCT STUDENT_ID) OVER(ORDER BY TRUNC(RSTS_DATE) ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) "UniqueHeadcount",
SUM(CREDIT_HR) OVER(ORDER BY TRUNC(RSTS_DATE) ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as "SumCredits",
TRUNC(RSTS_DATE) as "DATE"
FROM
REGISTRATIONS
这个查询方式更简短(yay) - 但有两个重要的问题我无法找到解决方法。首先,它与COUNT DISTINCT不起作用(通过设计,显然?)。所以我暂时评论了一下,但后来遇到了第二个问题:它忽略了TRUNC()函数。 RSTS_DATE,虽然看起来只是一个日/月/年值,当你在它上面运行SELECT时,实际上也保留了时间,所以我得到的结果集不是简单地在日期上求和,而是在时间上 - 因此,我的处理数据每天返回数百条记录(每个单独的课程注册一个记录),而不是每天一条记录。例如:
UniqueHeadcount SumCredits Date
1 3 01-JAN-12
1 5 02-JAN-12
2 6 03-JAN-12 (hidden time: 07:32:27)
2 7 03-JAN-12 (hidden time: 08:01:33)
不是我追求的目标。
所以我正在寻找专业知识 - 如果我到目前为止所解释的是有意义的 - 是否有另一种使用OVER子句的方法,或者可能还有PLSQL的另一个特性我应该用于此?如果你不知道,我在PLSQL中并不强大,但是如果有人能给我一些方向 - 即使只是谷歌的话,我也会感谢你的帮助。
由于
答案 0 :(得分:1)
试试这个:
WITH CRdata AS
(
SELECT COUNT(DISTINCT STUDENT_ID) AS UniqueHeadcount,
SUM(CREDIT_HR) AS SumCredits,
TRUNC(RSTS_DATE) RSTS_DATE
FROM REGISTRATIONS
GROUP BY TRUNC(RSTS_DATE)
)
SELECT SUM(UniqueHeadcount) OVER(ORDER BY RSTS_DATE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS UniqueHeadcount,
SUM(SumCredits) OVER(ORDER BY RSTS_DATE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS SumCredits,
RSTS_DATE
FROM CRdata