[英]Access SQL return nth row for each given field
Let's say I have a query that returns the following data: 假设我有一个返回以下数据的查询:
id date
-- ------
1 2015-01-12
1 ... // here I might have X more rows
1 2015-06-30
2 2015-01-12
2 ... // here I might have Y more rows
2 2015-05-20
...
Given that X, Y >= 120 and X != Y
and the order of the query is id, date ASC
I want a way to retrieve the record number 120 for id 1 and the 120 for the id 2 (and so on for each different ID), something like: 给定X, Y >= 120 and X != Y
并且查询的顺序是id, date ASC
我想要一种方法来检索id为1的记录号120和id为2的记录号120(依次类推)不同的ID),例如:
id date
-- --------
1 2015-03-24 // this is the record 120 for id = 1
2 2015-04-26 // this is the record 120 for id = 2
...
Notice that the dates don't follow a sequential order (you may have a gap between one row and the next one). 请注意,日期不是按照顺序排列的(一行和下一行之间可能会有间隔)。
Is there a direct SQL solution for my problem? 我的问题是否有直接的SQL解决方案? (I know I can use vba to achieve my goal but I rather stay with SQL) (我知道我可以使用vba来实现我的目标,但我宁愿使用SQL)
As a clarification note, see this example. 作为说明,请参见此示例。 Given the following resultset: 给定以下结果集:
id date
-- ------
1 2015-01-12 // this is record 1 for id = 1
1 2015-01-13 // this is record 2 for id = 1
1 2015-01-20 // this is record 3 for id = 1
1 2015-01-21 // this is record 4 for id = 1
...
1 2015-03-22 // this is record 118 for id = 1
1 2015-03-23 // this is record 119 for id = 1
1 2015-03-24 // this is record 120 for id = 1
1 2015-03-25 // this is record 121 for id = 1
...
1 2015-06-30 // this is the last row for id = 1
2 2015-01-12 // this is record 1 for id = 2
2 2015-01-13 // this is record 2 for id = 2
...
2 2015-04-25 // this is record 120 for id = 2
...
2 2015-05-20 // this is the last record for id = 2
The result should be: 结果应为:
id date
-- --------
1 2015-03-24
2 2015-04-26
Remember, I have at least 120 records for each ID, this is a fact (I have a query that gives only the IDs with more than 119 records) 请记住,我每个ID至少有120条记录,这是事实(我有一个查询,仅给出具有119条以上记录的ID)
I've tried to play with the SELECT TOP
directive, but I fail to achieve the results I want as I cannot apply it direcly: I don't want the top 120 and then get the last row as I want the last one of the TOP 120 for each ID. 我尝试使用SELECT TOP
指令,但是由于无法直接应用它而无法达到我想要的结果:我不希望前120个,然后获得最后一行,因为我想要最后一个每个ID的前120名。
My goal would be to have something like: 我的目标是拥有这样的东西:
SELECT id, 120thRow(date)
FROM table
GROUP BY id;
unfortunatelly I don't know how to implement the 120thRow function in access. 不幸的是,我不知道如何在访问中实现120thRow函数。
Does this work in Access? 这在Access中有效吗?
select t.*
from table as t
where t.date = (select top 1 date
from (select top 120 date
from table t2
where t2.id = t.id
order by date
) as tt
order by date desc
);
EDIT: 编辑:
I guess MS Access doesn't allow nesting in the correlation clause. 我想MS Access不允许在相关子句中嵌套。 You can do this more painfully as: 您可以通过以下方式更痛苦地完成此操作:
select t.*
from table as t join
(select t.id, max(t.date) as maxdate
from table as t
where t.date = (select top 120 date
from table as t2
where t2.id = t.id
order by date
)
) tt
on t.id = tt.id and t.date = tt.maxdate;
Sorry for my previous answer, I misunderstood you. 对不起,我以前的回答,我误会了你。 I have another approach but in SQL. 我有另一种方法,但在SQL中。 I am almost sure that it does not work in Access but might give you an idea. 我几乎可以肯定它在Access中不起作用,但可能会给您一个想法。
-- start: this is just preparation of some sample data
declare @t table (id int, date datetime)
declare @id int, @d datetime, @c int
set @c = 0
set @id = 1
set @d = '2015-01-01'
while @c <= 125
begin
insert into @t values (@id, @d)
set @d = dateadd(day, 1, @d)
set @c = @c + 1
end
set @c = 0
set @id = 2
set @d = '2015-01-02'
while @c <= 125
begin
insert into @t values (@id, @d)
set @d = dateadd(day, 1, @d)
set @c = @c + 1
end
-- end: this is just preparation of some sample data
-- this is somewhat like what you need:
select id, date from
(select id, date, row_number() over (partition by id order by date) as rc from @t) as mytable
where rc = 120
In the end, I've managed a way to put a row counter for each day and ID like so: 最后,我设法了一种为每天和ID放置一个行计数器的方法,如下所示:
select id, date,
(
select count(date)
from table As t1
where t1.id = t.id
and t1.date <= t.date
) As rowNum
from table As t
From here on it's just a matter of selecting from this resultset the rows which has rownum = 120 and game over. 从这里开始,只需从该结果集中选择rownum = 120并结束游戏的行即可。
Hi I think this must work for you. 嗨,我认为这必须为您工作。
with Records AS
(select row_number() over(order by sort_column_name) as 'row', *
from table_name) select * from records where row=n
sort_column_name
– mention the name of the column which is sorting the table. sort_column_name
–提及对表进行排序的列的名称。 n
– row number n
–行号 table_name
– mention the name of the table table name table_name
–提及表的名称表名
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.