SQL:为每个组ID选择前2个日期

SQL:为每个组ID选择前2个日期,sql,date,select,sql-server-2000,Sql,Date,Select,Sql Server 2000,我有一个包含如下条目的表,当涉及日期时,我正在努力进行分组 id ref startDate ---- ----- ------------- 1 001 01-01-2013 2 001 03-02-2013 3 002 31-01-2013 4 002 15-01-2013 5 001 05-06-201

我有一个包含如下条目的表,当涉及日期时,我正在努力进行分组

  id    ref    startDate     
 ----  ----- -------------  
   1    001     01-01-2013       
   2    001     03-02-2013       
   3    002     31-01-2013       
   4    002     15-01-2013       
   5    001     05-06-2013 ....      
我要做的是为每个ref选择前两个最长日期,这样我就可以得到以下结果

  id    ref    startDate     
 ----  ----- -------------  
   5    001     05-06-2013   
   2    001     03-02-2013       
   3    002     31-01-2013       
   4    002     15-01-2013  
我想这意味着要按照

SELECT *
FROM   TABLE a
JOIN   (SELECT startDate
        FROM   TABLE b
        JOIN   TABLE c
        ON     b.ref = c.ref AND b.startDate >= c.startDate
        GROUP BY ref) AS d
ON     a.ref = b.ref

不幸的是,我使用的是SQL2000,所以分区是不可能的

下面是一个使用相关子查询的方法:

SELECT *
FROM TABLE t
WHERE (select count(*)
       from Table t2
       where t2.ref = t.ref and
             t2.date >= t.date
      ) <= 2;
这假设每个组中的日期都是唯一的

是一个SQL小提琴显示它的工作

编辑:

如果日期不唯一,则可以修改此选项,以通过以下方式获取前两个日期的顶行:

SELECT *
FROM TABLE t
WHERE (select count(distinct t2.date)
       from Table t2
       where t2.ref = t.ref and
             t2.date >= t.date
      ) <= 2;
SELECT *
FROM TABLE t
WHERE (select count(*)
       from Table t2
       where t2.ref = t.ref and
             (t2.date > t.date or t2.date = t.date and t2.id <= t.id)
      ) <= 2;
或者,可以通过这种方式将其限制为正好两行:

SELECT *
FROM TABLE t
WHERE (select count(distinct t2.date)
       from Table t2
       where t2.ref = t.ref and
             t2.date >= t.date
      ) <= 2;
SELECT *
FROM TABLE t
WHERE (select count(*)
       from Table t2
       where t2.ref = t.ref and
             (t2.date > t.date or t2.date = t.date and t2.id <= t.id)
      ) <= 2;
请检查这个

DECLARE @REF_TABLE AS TABLE(ID INT IDENTITY(1,1),REF VARCHAR(10))
DECLARE @LOOP_COUNT INT
DECLARE @ID INT=1
DECLARE @REF VARCHAR(10)
SELECT @LOOP_COUNT=COUNT(*) FROM @REF_TABLE
SELECT * INTO #TEMP FROM YOURTABLE WHERE 1=2
INSERT INTO @REF_TABLE SELECT DISTINCT REF FROM YOURTABLE
WHILE @LOOP_COUNT<@ID
BEGIN
SELECT @REF=REF FROM @REF_TABLE WHERE ID=@ID
INSERT INTO #TEMP SELECT TOP 2 * FROM YOURTABLE WHERE REF=@REF ORDER BY startDate DESC
SELECT @ID=@ID+1

END

SELECT * FROM #TEMP`

只需在查询中的某个地方将此子句修改为适合您的需要,它应该只为您提供特定引用的前两个起始日期

WHERE b.StartDate IN 

(SELECT TOP 2 StartDate FROM b WHERE a.ref = b.ref ORDER BY StartDate DESC)

由于您的联接看起来是您最初尝试使用的联接,请将您拥有的联接替换为上面的WHERE。请确保编辑它,使其与您的实际表名相匹配

我认为这提供了您所需要的内容。我知道它有点长,因为我们不能使用CTE或任何windows功能

出于测试目的,我添加了两条额外的记录,即相同的ref和重复的startdate,以及不同的ref和相同的startdate,并进行了注释


它只为大多数记录带来了1个条目,尽管它们大约有5+个条目。日期也不重复。@Hazel。我可能猜你的日期实际上是带有时间的datetime值。它们是datetime,但都是00:00:00.000。@Hazel。查看SQL小提琴。答案中的代码确实有效。它应该是SELECT TOP 2 STARTDATE查询中的about需要在哪里?我是否需要删除一些我已经编写的代码?由于您的连接看起来像是您最初尝试使用的连接,请将您拥有的连接替换为上面的where。确保对其进行编辑,使其与实际表名匹配。