我希望得到一位专家的帮助。
在SQL SELECT语句中我试图获取去年每月数据的最后一天。 例如,我很容易得到每个月的最后一天并将其加入我的数据表,但问题是,如果该月的最后一天没有数据,则没有返回的数据。我需要的是让SELECT返回最后一天的月份数据。
这可能很容易,但说实话,我的大脑屁开始受伤了。
我附上了下面的选项,用于返回过去12个月中该月最后一天的数据。
提前感谢您的帮助!
SELECT fd.cust_id,fd.server_name,fd.instance_name,
TRUNC(fd.coll_date) AS coll_date,fd.column_name
FROM super_table fd,
(SELECT TRUNC(daterange,'MM')-1 first_of_month
FROM (
select TRUNC(sysdate-365,'MM') + level as DateRange
from dual
connect by level<=365)
GROUP BY TRUNC(daterange,'MM')) fom
WHERE fd.cust_id = :CUST_ID
AND fd.coll_date > SYSDATE-400
AND TRUNC(fd.coll_date) = fom.first_of_month
GROUP BY fd.cust_id,fd.server_name,fd.instance_name,
TRUNC(fd.coll_date),fd.column_name
ORDER BY fd.server_name,fd.instance_name,TRUNC(fd.coll_date)
答案 0 :(得分:2)
您可能需要对数据进行分组,以便每个月的数据都在组中,然后在组内选择最大日期。子查询可能是:
SELECT MAX(coll_date) AS last_day_of_month
FROM Super_Table AS fd
GROUP BY YEAR(coll_date) * 100 + MONTH(coll_date);
这假定存在YEAR()和MONTH()函数以从日期中提取年和月作为整数值。显然,这并不限制日期范围 - 你也可以这样做。如果您没有Oracle中的函数,那么您可以进行某种操作以获得相同的结果。
使用Rhose的信息(谢谢):
SELECT MAX(coll_date) AS last_day_of_month
FROM Super_Table AS fd
GROUP BY TO_CHAR(coll_date, 'YYYYMM');
这实现了相同的净结果,将同一日历月中的所有日期放入一个组中,然后确定该组中的最大值。
答案 1 :(得分:1)
将上述部分放在一起,这样的事情对你有用吗?
SELECT fd.cust_id,
fd.server_name,
fd.instance_name,
TRUNC(fd.coll_date) AS coll_date,
fd.column_name
FROM super_table fd,
WHERE fd.cust_id = :CUST_ID
AND TRUNC(fd.coll_date) IN (
SELECT MAX(TRUNC(coll_date))
FROM super_table
WHERE coll_date > SYSDATE - 400
AND cust_id = :CUST_ID
GROUP BY TO_CHAR(coll_date,'YYYYMM')
)
GROUP BY fd.cust_id,fd.server_name,fd.instance_name,TRUNC(fd.coll_date),fd.column_name
ORDER BY fd.server_name,fd.instance_name,TRUNC(fd.coll_date)
答案 2 :(得分:1)
如果支持ANSI row_number()
,这是另一种方法:
with RevDayRanked(itemDate,rn) as (
select
cast(coll_date as date),
row_number() over (
partition by datediff(month,coll_date,'2000-01-01') -- rewrite datediff as needed for your platform
order by coll_date desc
)
from super_table
)
select itemDate
from RevDayRanked
where rn = 1;
编号为1的行将在该月的最后一个活动日期的行中进行不确定性选择,因此您不需要区分。如果您希望在这些日期的所有行中使用表格中的信息,请使用rank()
天数而不是row_number()
超过coll_date值,因此对于上一个活动日期的任何行,都会显示值1月,并选择您需要的其他列:
with RevDayRanked(cust_id, server_name, coll_date, rk) as (
select
cust_id, server_name, coll_date,
rank() over (
partition by datediff(month,coll_date,'2000-01-01')
order by cast(coll_date as date) desc
)
from super_table
)
select cust_id, server_name, coll_date
from RevDayRanked
where rk = 1;
如果不支持row_number()
和rank()
,则另一种方法(对于上面的第二个查询)。从表格中选择同一月中某一行中没有行的所有行。
select
cust_id, server_name, coll_date
from super_table as ST1
where not exists (
select *
from super_table as ST2
where datediff(month,ST1.coll_date,ST2.coll_date) = 0
and cast(ST2.coll_date as date) > cast(ST1.coll_date as date)
)
如果你必须做很多这样的事情,看看你是否可以创建一个包含cast(coll_date as date)
的计算列和datediff(month,'2001-01-01',coll_date)
月份指标的索引。这将使更多的谓词成为SARG。