我有一个非常大的查询,这给我带来了一些麻烦,因为一个连接可以返回多行。我只想在这个结果集中使用最新的行(由日期字段标识),但我似乎无法将正确的查询放在一起以使其正常工作。
我需要MAX date的查询是:
SELECT custid,reason,date FROM OPT opt WHERE opt.custid = 167043;
真的通过连接找到了custid,但为了简单起见,我已将其添加到where子句中。此查询产生以下结果:
custid grunn date
167043 "Test 1" 19.10.2005 12:33:18
167043 "Test 2" 28.11.2005 16:23:35
167043 "Test 3" 14.06.2010 15:43:16
如何从此结果集中仅检索一条记录?那个记录是日期最长的记录吗?最终我把它放到一个大查询中,这个查询有很多连接,所以希望我可以将这个例子用于我更大的查询。
答案 0 :(得分:1)
您可以使用分析函数来解决它。尝试这样的事情:
select custid
,reason
,date
from (select custid
,reason
,date
,row_number() over(partition by cust_id order by date desc) as rn
from opt)
where rn = 1;
这是它的工作原理:结果集分为cust_id(partition by
)组。在每个组中,行将按日期列按降序排序(order by
)。组中的每一行将被分配一个从1到N的序列号(row_number
)。
这样,具有最高日期值的行将被分配1,第二个最新的2,第三个最新的3等。
最后,我只选择nr = 1的行,基本上过滤掉其他行。
答案 1 :(得分:1)
你可以这样做:
SELECT * FROM
( SELECT custid,reason,date FROM OPT opt WHERE opt.custid = 167043
ORDER BY date DESC
)
WHERE ROWNUM = 1;
答案 2 :(得分:0)
或者以其聚合形式使用LAST
函数的另一种方式。
with my_source_data as (
select 167043 as custid, 'Test 1' as reason, date '2010-10-01' as the_date from dual union all
select 167043 as custid, 'Test 2' as reason, date '2010-10-02' as the_date from dual union all
select 167043 as custid, 'Test 3' as reason, date '2010-10-03' as the_date from dual union all
select 167044 as custid, 'Test 1' as reason, date '2010-10-01' as the_date from dual
)
select
custid,
max(reason) keep (dense_rank last order by the_date) as reason,
max(the_date)
from my_source_data
group by custid
我发现这非常有用,因为它将查找最后一行和值all的过程滚动到一个。如果分组和顺序的组合不是确定性的,则使用MAX
(或其他聚合函数,例如MIN
)。
此函数基本上会根据分组获取列的内容,按给定的顺序对其进行排序,然后取最后一个值。
答案 3 :(得分:0)
而不是使用row_number()我认为最好选择你真正想要选择的内容(例如最后一个日期)
SELECT custid
, reason
, date
from
(
SELECT custid
, reason
, date
, max(opt.date) over (partition by opt.custid order by opt.date) last_date
FROM OPT opt
WHERE opt.custid = 167043;
)
where date = last_date
答案 4 :(得分:0)
使用ROW_NUMBER和KEEP的两个解决方案都很好。我倾向于在检索大量列时更喜欢ROW_NUMBER,并保留一个或两个列的KEEP,否则你将不得不处理重复项,并且该语句将变得非常难以理解。
但是对于少量列,KEEP应该表现更好