我想从我的数据集中选择最早的日期和时间,并仅显示符合要求的那些行。并显示3列。
我得到它按日期和时间以正确的顺序显示数据。我怎样才能让它显示具有最小值的数据?我尝试使用first,limit和top x,但它们不起作用,并且不正是我需要的,因为答案可能有多个值。
这是我的示例sql:
Select report, date, time
From events
order by date, time
答案 0 :(得分:4)
试试这个:
SELECT report, date, time
FROM (SELECT report, date, time,
ROW_NUMBER() OVER(PARTITION BY report ORDER BY date ASC, time ASC) AS RowNum
From events
) AS CTE
WHERE CTE.RowNum = 1
答案 1 :(得分:1)
猜测数据类型并不清楚,但这样的事情可能有用(例如使用CTE生成虚拟数据):
with events as (
select 'report1' as report, '01/01/2012' as date_field, '0800' as time_field
from dual
union all select 'report1', '01/01/2012', '0900' from dual
union all select 'report1', '01/02/2012', '0930' from dual
union all select 'report2', '01/01/2012', '0900' from dual
union all select 'report2', '01/01/2012', '0900' from dual
union all select 'report2', '01/01/2012', '1000' from dual
)
select report, date_field, time_field
from (
select report, date_field, time_field,
row_number() over (partition by report
order by to_date(date_field, 'MM/DD/YYYY'), time_field) as rn
from events
)
where rn = 1
order by report;
REPORT DATE_FIELD TIME
------- ---------- ----
report1 01/01/2012 0800
report2 01/01/2012 0900
您可能有不同的日期格式掩码;当你提到“军事时间”时,我假设美国格式。
根据您想要处理关系的方式,您需要rank
或dense_rank
而不是row_number
。有关详细信息,请参阅analytic functions的文档。正如Justin所指出的那样,你可能想要rank
,它使用相同的数据给出:
REPORT DATE_FIELD TIME
------- ---------- ----
report1 01/01/2012 0800
report2 01/01/2012 0900
report2 01/01/2012 0900
内部选择会添加一个额外的rn
列,为每个结果分配排名; report
的每个值至少会有一行被分配1
(如果使用rank
,则只有一行),可能包含2
,{{1}的行3
的那个人将拥有该报告的最早日期/时间。外部查询然后通过1
子句过滤到仅显示排名1
的那些,因此仅为每个where rn = 1
提供具有最早日期/时间的数据 - 其余的被丢弃。
答案 2 :(得分:1)
假设每一行都有一个有效格式化的日期和时间组件,这样的事情应该有效。
SELECT report,
dt,
time
FROM (SELECT report,
dt,
time,
rank() over (partition by report
order by to_date( dt || ' ' || time, 'MM/DD/YYYY HH24MI' ) asc) rnk
FROM events)
WHERE rnk = 1
但是,从数据模型的角度来看,您应始终将日期存储在DATE
列中,而不是尝试将其存储在VARCHAR2
列中。由于您需要日期比较和排序语义,因此您必须将数据转换为DATE
,这在运行时很昂贵。并且很可能有人最终会在列中以不同的格式存储数据或存储无效的字符串(即'02 / 29/2011'的一天),这将导致您的查询开始生成错误。