访问SQL返回每个给定字段的第n行

时间:2015-02-12 12:59:31

标签: sql ms-access ms-access-2003

我的问题

假设我有一个返回以下数据的查询:

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
...

鉴于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
...

请注意,日期不遵循连续顺序(您可能在一行与下一行之间存在差距)。

我的问题是否有直接的SQL解决方案?(我知道我可以使用vba来实现我的目标,但我宁愿继续使用SQL)

作为澄清说明,请参阅此示例。给出以下结果集:

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

结果应为:

id      date
--    --------
1     2015-03-24
2     2015-04-26

请记住,每个ID至少有120条记录,这是事实(我的查询只提供超过119条记录的ID)

尝试解决方案

我试图使用SELECT TOP指令,但我未能达到我想要的结果,因为我无法直接应用它:我不想要前120名然后获得最后一行,因为我想要每个ID的最后一个TOP 120。

编辑(第二次)澄清

我的目标是拥有类似的东西:

SELECT id, 120thRow(date)
FROM table
GROUP BY id;

不幸的是,我不知道如何在访问中实现 120thRow 功能。

4 个答案:

答案 0 :(得分:1)

这是否适用于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
               );

编辑:

我猜MS Access不允许在关联子句中嵌套。你可以更痛苦地做到这一点:

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;

答案 1 :(得分:1)

对不起我之前的回答,我误解了你。我有另一种方法,但在SQL中。我几乎可以肯定它在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

答案 2 :(得分:1)

最后,我设法为每天设置一个行计数器和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

从这里开始,只需从结果集中选择rownum = 120且游戏结束的行。

答案 3 :(得分:0)

嗨,我认为这一定对您有用。

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 - 提及对表格进行排序的列的名称。
  • n - 行号
  • table_name - 提及表格表名称的名称