【问题标题】:SQL keeping count of occurrences through a sliding windowSQL 通过滑动窗口记录出现次数
【发布时间】:2013-04-08 10:11:55
【问题描述】:

在上一个问题中(请参考:SQL Keeping count of occurrences)我需要统计一个变量出现的次数。

提供的代码如下:

SELECT 
    [Date], Code, 
    [Count] = COUNT(*) OVER (PARTITION BY Code ORDER BY [Date] ROWS UNBOUNDED PRECEDING)
FROM dbo.YourTable
ORDER BY [Date];

但是,现在我需要对该代码进行改进:

假设我有下表:

   Date          | Code
   ------------------------
   2010/01/01    | 25
   2010/01/01    | 22
   2010/01/01    | 23
   2010/01/01    | 25
   2010/01/02    | 23
   2010/01/02    | 23
   2010/01/03    | 23
   2010/01/04    | 23
   2010/01/05    | 23
   2010/01/06    | 23
   2010/01/07    | 23
   .....
   2013/03/02    | 21

现在,我需要计算特定时间段内出现的次数。期望的输出如下(为简单起见,假设时间范围为 n=2 天)

    Date         | Code  |  Occurrences
   ------------------------------------
   2010/01/01    | 25    |      1
   2010/01/01    | 22    |      1
   2010/01/01    | 23    |      1
   2010/01/01    | 25    |      2
   2010/01/02    | 23    |      2
   2010/01/02    | 23    |      3
   2010/01/03    | 23    |      3 -> We are not considering the occurence in 2011/01/01 as it is out of the scope now
   2010/01/04    | 23    |      2 -> Considers only occurrences in 01/03 and 01/04 
   2010/01/05    | 23    |      2
   2010/01/06    | 23    |      2
   2010/01/07    | 23    |      2
   .....
   2013/03/02    |  21   |      1

也就是说,我需要知道代码“x”在过去“n”个月内出现在我的表中的次数。

这是在 SQL Server 2012 中运行的。

提前谢谢你。

【问题讨论】:

  • SQL Server 的哪个版本?

标签: sql sql-server count sql-server-2012


【解决方案1】:

将选项与CTECROSS APPLY 运算符和ROW_NUMBER 排名函数一起使用

 ;WITH cte AS
 (
  SELECT [Date], Code
  FROM dbo.YourTable  
  GROUP BY [Date], Code
  )
  SELECT c.Date, c.Code, o.Occurrences
  FROM cte c 
    CROSS APPLY (
                 SELECT t2.[Date], t2.Code,
                        ROW_NUMBER() OVER(PARTITION BY c.[Date] ORDER BY t2.[Date]) AS Occurrences        
                 FROM dbo.YourTable t2
                 WHERE c.Code = t2.Code
                   AND DATEDIFF(day, t2.[Date], c.[Date]) BETWEEN 0 AND 1
                 ) o
  WHERE c.Code = o.Code AND c.[Date] = o.[Date] 
  ORDER BY c.[Date]

SQLFiddle上的演示

为了提高性能使用这个索引

CREATE INDEX x ON dbo.YourTable([Date], Code)

【讨论】:

  • 感谢@Alexander,它似乎在演示中完美运行。只有一个问题:如果我创建索引,我能否将输出表复制到新表中?
  • @Alfons 什么表:临时表、变量表或现有表以及为什么需要复制?
  • 我想将查询结果复制到一个新表中,因为我需要使用它并将此信息用于其他表。我需要的特定表将是查询的结果,即在 sqlfiddle 演示中生成的表。
  • 没问题,您可以在表源上创建索引,如果需要进一步在新表上创建新索引,您也可以这样做。
【解决方案2】:

请尝试:

SELECT 
    *, 
    ROW_NUMBER() OVER (PARTITION BY Code ORDER BY Code) Occurrences 
FROM YourTable
ORDER BY Occurrences

【讨论】:

    【解决方案3】:

    试试这个查询

    查询 1

    select 
      count(*) as CountOccurance,
      code
    from 
      tbl 
    where 
      code = 21 and 
      date between dateadd(m, -5, SYSDATETIME ()) and SYSDATETIME ()
    group by 
      code
    

    结果

    | COUNTOCCURANCE | CODE |
    -------------------------
    |              1 |   21 |
    

    如果您想计算所有代码值,请删除 where 子句..

    SQLFIDDLE

    希望对你有帮助

    【讨论】:

    • 感谢您的回复。但是,不幸的是,它没有产生所需的输出。在这种情况下,我不想在输出中引入过滤器(日期之间......),而是通过计算引入这种过滤器。我需要保留我拥有的行数,以计算附加到日期的代码(注意日期是重复的)在前“n”个月中出现的次数。我希望这个问题的解释现在更清楚了。
    • 没听懂你在说什么。你只需要添加n,它表示我们必须搜索记录的月数。如果我错了,你能显示您想要的表格格式输出...
    【解决方案4】:

    试试这个

         SELECT * FROM 
                (SELECT 
                ROW_NUMBER() OVER (PARTITION BY Code,[Date] ORDER BY [Date]) AS NO,
                [Date], Code, 
                COUNT(1) OVER (PARTITION BY Code ,[Date]) AS [Count] 
            FROM dbo.YourTable Where date between dateadd(m, -n, GETDATE()) and GETDATE() ) 
    AS T1 WHERE No = 1
            ORDER BY [Date];
    

    或者试试这个。

     SELECT * FROM 
                    (SELECT 
                    ROW_NUMBER() OVER (PARTITION BY Code,[Date] ORDER BY [Date]) AS NO,
                    [Date], Code, 
                    COUNT(1) OVER (PARTITION BY Code ,[Date]) AS [Count] 
                FROM dbo.YourTable Where 
        Code = 25 And
        date between dateadd(m, -n, GETDATE()) and GETDATE() ) AS T1 WHERE No = 1
                ORDER BY [Date];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-13
      • 2017-12-29
      • 2022-01-03
      • 1970-01-01
      • 2019-05-07
      • 2020-08-08
      • 2017-09-23
      • 1970-01-01
      相关资源
      最近更新 更多