Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 根据日期范围选择最大记录数。(日期在相互之间的6个月内)_Sql Server_Tsql_Sql Server 2005 - Fatal编程技术网

Sql server 根据日期范围选择最大记录数。(日期在相互之间的6个月内)

Sql server 根据日期范围选择最大记录数。(日期在相互之间的6个月内),sql-server,tsql,sql-server-2005,Sql Server,Tsql,Sql Server 2005,我有一张日期表 我需要能够选择相互之间在6个月内存在的最大数量的记录 然后是下一个最大数量的记录,依此类推,直到选中所有记录 这是数据 1 19-Oct-2007 2 03-Dec-2007 3 16-Oct-2009 4 26-Oct-2009 5 30-Oct-2009 6 01-Nov-2009 7 16-Nov-2009 8 30-Nov-2009 9 11-Dec-2009 10 25-Dec-2009 11 01-Jan-2010 12 21-Jan-2010

我有一张日期表

我需要能够选择相互之间在6个月内存在的最大数量的记录

然后是下一个最大数量的记录,依此类推,直到选中所有记录

这是数据

1  19-Oct-2007
2  03-Dec-2007
3  16-Oct-2009
4  26-Oct-2009
5  30-Oct-2009
6  01-Nov-2009
7  16-Nov-2009
8  30-Nov-2009
9  11-Dec-2009
10  25-Dec-2009
11  01-Jan-2010
12  21-Jan-2010
13  27-Jan-2010
14  28-Jan-2010
15  28-Jan-2010
16  12-Feb-2010
17  12-Feb-2010
18  27-Feb-2010
19  09-Mar-2010
20  22-Mar-2010
21  26-Mar-2010
22  01-Apr-2010
23  22-Oct-2010
24  15-Oct-2011
25  18-Oct-2011
26  26-Oct-2011
27  16-Nov-2011
28  18-Nov-2011
29  19-Nov-2011
30  26-Nov-2011
31  29-Nov-2011
32  29-Nov-2011
33  30-Nov-2011
34  06-Dec-2011
35  16-Dec-2011
36  17-Dec-2011
37  20-Dec-2011
38  28-Dec-2011
39  01-Jan-2012
40  01-Jan-2012
41  09-Jan-2012
42  13-Jan-2012
43  27-Jan-2012
44  01-Feb-2012
45  23-Feb-2012
46  29-Feb-2012
47  01-Mar-2012
48  01-Mar-2012
49  01-Mar-2012
50  02-Mar-2012
51  04-Mar-2012
52  04-Mar-2012
53  05-Mar-2012
54  05-Mar-2012
55  17-Mar-2012
56  23-Mar-2012
57  24-Mar-2012
58  01-Apr-2012
59  03-Apr-2012
60  04-Apr-2012
一个可能的解决办法是选择

  • 记录24-60(彼此之间在172天内)
  • 记录23(不在前一个/下一个日期的6个月内)
  • 记录3-22(彼此在167天内)
  • 记录1-2(彼此在45天内)
(我从最大日期开始,并向后选择。这可能不是最佳解决方案)

选择d1.date,count(*)
起始日期为d1,带有(nolock)
将日期作为d2与(nolock)连接
日期差(mm,d2.日期,d1.日期)<6
按d1.1日期分组
按计数排序(*)说明
我考虑过

  • 6个月=180天
  • 如果日期之间的差异大于180天,则它们将在列表中列出
  • 试试这个:

    create table #list (id int, dt datetime  )
    -- insert you data into #list
    
    select s1.id as ID_1, s1.dt as Date_2 , s2.id as ID_2, s2.dt as Date_2 
    ,abs( datediff(day, s2.dt, s1.dt) ) diff_in_days
    from #list s1 , #list s2 
    order by  case when abs(datediff(day, s2.dt, s1.dt) ) > 180 then 1
    else  abs(datediff(day, s2.dt, s1.dt)) end  desc 
    

    我使用了我自己的测试数据,这是非常复杂的东西。使用光标可能更容易处理。但我不太喜欢用光标。我已经尽了最大努力:

    declare @t table(record int, date datetime)
    insert @t values(1,'19-Oct-2007'),
    (2,'03-Dec-2007'),
    (3,'2-may-2009'),
    (4,'16-Oct-2009'),
    (5,'26-Oct-2009'),
    (6,'30-Oct-2009'),
    (7,'01-Nov-2009'),
    (8,'16-Nov-2009'),
    (9,'30-Nov-2009'),
    (10,'11-Dec-2009'),
    (11,'11-Dec-2010'),
    (12,'11-Dec-2010'),
    (13,'11-Dec-2010')
    
    ;with a as
    (
      select datediff(day, t1.date, t2.date) daysapart, 
      row_number() over (order by count desc) rn,
      b.count, 
             t1.record fromrecord, 
             t2.record torecord
      from @t t1
      join @t t2
      on t1.date <= t2.date 
         and dateadd(month, 6, t1.date) > t2.date 
         and t1.record <= t2.record
      cross apply (select count(*) count from @t where record between t1.record and t2.record) b
    )
    , b as
    (
        select * from a where not exists 
        (select 1 from a b where (a.fromrecord between b.fromrecord and b.torecord
          or a.torecord between b.fromrecord and b.torecord)
          and a.rn > b.rn and not exists(select 1 from a c where 
          (b.fromrecord between c.fromrecord and c.torecord
          or b.torecord between c.fromrecord and c.torecord)
          and b.rn > c.rn))
    )
    select count, fromrecord, torecord, daysapart from b
    

    下面是解决这个问题的迭代方法,目前我没有比这更好的建议了。不过,它应该会起作用:

    WITH ranked AS (
      SELECT *, rnk = ROW_NUMBER() OVER (ORDER BY Date DESC)
      FROM data
    ),
    marked AS (
      SELECT
        rnk,
        Date,
        GroupDate = date
      FROM ranked
      WHERE rnk = 1
      UNION ALL
      SELECT
        r.rnk,
        r.Date,
        GroupDate = CASE
          WHEN m.GroupDate > DATEADD(MONTH, 6, r.Date) THEN r.Date
          ELSE m.GroupDate
        END
      FROM ranked r
      INNER JOIN marked m ON r.rnk = m.rnk + 1
    )
    SELECT
      MinDate     = MIN(Date),
      MaxDate     = MAX(Date),
      [RowCount]  = COUNT(*),
      RangeLength = DATEDIFF(DAY, MIN(Date), MAX(Date))
    FROM marked
    GROUP BY
      GroupDate
    ORDER BY
      GroupDate
    
    就是

  • 最后一个日期用于范围检查和组标记

  • 后续(之前)日期将被处理,直到比遇到标记早半年

  • 找到的日期将成为新的组标记,该过程将从步骤1继续,直到不再有行为止

  • 在继续迭代之前,将对行进行排序。但是,如果您有一个列保证包含唯一的连续值,并且没有空格,则可以使用该列而不是排名数字

    以下是它在原始帖子中给出的样本结果:

    MinDate     MaxDate     RowCount     RangeLength
    ----------  ----------  -----------  -----------
    2007-10-19  2007-12-03  2            45
    2009-10-16  2010-04-01  20           167
    2010-10-22  2010-10-22  1            0
    2011-10-15  2012-04-04  37           172
    

    整个脚本,包括设置,都可以找到并使用。

    我尝试了你的脚本,但没有给出正确或非常正确的结果。这是我先前的修正comment@t-clausen.dk你能告诉我1>在问题的给定数据集中,我的第一行输出应该是什么吗?对我来说,理解是-在数据集中,找出以6M为单位的日期之间的差异,并按降序排列。所以你假设作者想要3600行作为结果集?不知道... 你能指定他想要什么吗?@t-clausen.dk我在SQL 2008 R2上测试了它。哪一部分对你不起作用?在你纠正语法后,结果才是错误的。试试@andryMI的脚本对不起,我写得太早了。这是不对的。@t-clausen.dk:我不确定我是否理解这个解决方案的问题所在,但我很想尝试解决它,特别是因为你已经对我的答案投了更高的票。用这些日期试试你的问题,应该很清楚:(1,'2012-01-01'),(2,'2012-01-01'),(3,'2012-03-01'),(4,'2012-03-01'),(5,'2012-08-01'))@克劳森:谢谢。我看不出我得到的结果有什么不对,但我想也许我们对这个问题的理解不同。我想我现在明白你是怎么理解的了(这可能比我的理解更正确)。你认为查询必须找到彼此相隔6个月的日期的最大子集,不是吗?最初文章中的一些线索,我一开始肯定错过了,确实支持这一观点。我认为可以使用递归CTE来找到一个(最大的)这样的子集。但是,到目前为止,找到所有这些似乎是一项复杂得多的任务。我同意这是一项复杂的任务。这正是我在我的查询中尝试的,它似乎有效。这有点令人兴奋,但它有效!我对您的解决方案的一个(相当小的)挑剔是这样的条件:
    datediff(day,t1.date,t2.date)介于0和180之间。我真的想把它改成:
    t2.date@AndriyM谢谢你的评论和好话。在日期问题上有很好的发现。我刚刚醒来并登录以更改它,因为它困扰着我。要不然我早上从来不会这么早起床。这将无法很好地扩展大型数据集
    
    WITH ranked AS (
      SELECT *, rnk = ROW_NUMBER() OVER (ORDER BY Date DESC)
      FROM data
    ),
    marked AS (
      SELECT
        rnk,
        Date,
        GroupDate = date
      FROM ranked
      WHERE rnk = 1
      UNION ALL
      SELECT
        r.rnk,
        r.Date,
        GroupDate = CASE
          WHEN m.GroupDate > DATEADD(MONTH, 6, r.Date) THEN r.Date
          ELSE m.GroupDate
        END
      FROM ranked r
      INNER JOIN marked m ON r.rnk = m.rnk + 1
    )
    SELECT
      MinDate     = MIN(Date),
      MaxDate     = MAX(Date),
      [RowCount]  = COUNT(*),
      RangeLength = DATEDIFF(DAY, MIN(Date), MAX(Date))
    FROM marked
    GROUP BY
      GroupDate
    ORDER BY
      GroupDate
    
    MinDate     MaxDate     RowCount     RangeLength
    ----------  ----------  -----------  -----------
    2007-10-19  2007-12-03  2            45
    2009-10-16  2010-04-01  20           167
    2010-10-22  2010-10-22  1            0
    2011-10-15  2012-04-04  37           172