Sql server 窗口函数和查询优化器

Sql server 窗口函数和查询优化器,sql-server,over-clause,Sql Server,Over Clause,我有一张结构如下的桌子 |anId| aDate|aNumber| ------------------------- | 1|2018-01-20| 100| | 1|2019-01-01| -100| | 1|2019-02-01| 10| | 2|2019-01-02| 40| 我有一个查询要返回,在特定日期,是否上一个(包括)数的总和为每个数>0 select anId, aDate, 1 as aStatus from (

我有一张结构如下的桌子

|anId|     aDate|aNumber|
-------------------------
|   1|2018-01-20|    100|
|   1|2019-01-01|   -100|
|   1|2019-02-01|     10|
|   2|2019-01-02|     40|
我有一个查询要返回,在特定日期,是否上一个(包括)数的总和为每个数>0

select
  anId,
  aDate,
  1 as aStatus
from (
  select
    anId,
    aDate,
    sum(aNumber) OVER (
      PARTITION BY anId
      ORDER BY aDate
      ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING
    ) as aSum
  from
    myTable
)
where
  aSum > 0
;
所以这个查询将返回

|anId|     aDate|aStatus|
-------------------------
|   1|2018-01-20|      1|
|   2|2019-01-02|      1|
|   1|2019-02-01|      1|
|anId|     aDate|aStatus|
-------------------------
|   1|2018-01-20|      1|
|anId|     aDate|aStatus|
-------------------------
|   2|2019-01-02|      1|
|   1|2019-02-01|      1|
现在,我已将查询转换为视图
myView
。我想在此视图中查询日期范围。我可以每天/每月/每年查询表,但我希望能够导出一个日期范围的查询结果,然后导出/追加下一个日期范围的结果

select
  anId,
  aDate,
  aStatus
from
  myView
where
  aDate between (2018-01-01) and (2018-12-31)
;
会回来吗

|anId|     aDate|aStatus|
-------------------------
|   1|2018-01-20|      1|
|   2|2019-01-02|      1|
|   1|2019-02-01|      1|
|anId|     aDate|aStatus|
-------------------------
|   1|2018-01-20|      1|
|anId|     aDate|aStatus|
-------------------------
|   2|2019-01-02|      1|
|   1|2019-02-01|      1|
第二年呢

select
  anId,
  aDate,
  aStatus
from
  myView
where
  aDate between (2019-01-01) and (2019-12-31)
;
应该回来

|anId|     aDate|aStatus|
-------------------------
|   1|2018-01-20|      1|
|   2|2019-01-02|      1|
|   1|2019-02-01|      1|
|anId|     aDate|aStatus|
-------------------------
|   1|2018-01-20|      1|
|anId|     aDate|aStatus|
-------------------------
|   2|2019-01-02|      1|
|   1|2019-02-01|      1|
允许我将结果缝合在一起,以获得原始的、未过滤的视图记录


好了,现在阶段已经设置好了,我对这种方法的担心是,当我从视图中过滤日期时,它会影响窗口函数


当我在2019年进行筛选时,加窗总和是否仍包括2018年的数量?我的日期范围过滤器是否会在总和之前应用于内部选择?

创建此问题后,我意识到它应该足够简单,可以对其进行测试

CREATE TABLE [dbo].[myTable](
    [anId] [char](36) NOT NULL,
    [aDate] [datetime2](7) NULL,
    [aNumber] [int] NULL
) ON [PRIMARY]
GO

insert into myTable(anId,aDate,aNumber) values ('1','2018-01-20',100);
insert into myTable(anId,aDate,aNumber) values ('1','2019-01-01',-100);
insert into myTable(anId,aDate,aNumber) values ('1','2019-02-01',10);
insert into myTable(anId,aDate,aNumber) values ('2','2019-01-20',40);
使用子选择而不是创建实际视图

返回:

|anId|     aDate|aStatus|
-------------------------
|   1|2018-01-20|      1|
|anId|     aDate|aStatus|
-------------------------
|   2|2019-01-02|      1|
|   1|2019-02-01|      1|


这将确认日期筛选器不会影响总和。然而,这让我担心子查询是次优的,因为它可能会在大量数据上运行求和。也就是说,当我想要2018年数据时,它是否还在计算2019年数据的总和?

在创建了这个问题之后,我意识到它应该足够简单,可以测试它

CREATE TABLE [dbo].[myTable](
    [anId] [char](36) NOT NULL,
    [aDate] [datetime2](7) NULL,
    [aNumber] [int] NULL
) ON [PRIMARY]
GO

insert into myTable(anId,aDate,aNumber) values ('1','2018-01-20',100);
insert into myTable(anId,aDate,aNumber) values ('1','2019-01-01',-100);
insert into myTable(anId,aDate,aNumber) values ('1','2019-02-01',10);
insert into myTable(anId,aDate,aNumber) values ('2','2019-01-20',40);
使用子选择而不是创建实际视图

返回:

|anId|     aDate|aStatus|
-------------------------
|   1|2018-01-20|      1|
|anId|     aDate|aStatus|
-------------------------
|   2|2019-01-02|      1|
|   1|2019-02-01|      1|


这将确认日期筛选器不会影响总和。然而,这让我担心子查询是次优的,因为它可能会在大量数据上运行求和。也就是说,当我需要2018年数据时,是否仍在计算2019年数据的总和?

从您的结果中,我想您可以扣除该总和将包括所有之前的行。否则,Id 1将不会有任何行,因为它将是负数。如果您将Sum列添加到视图中,并查看带过滤器和不带过滤器的结果,则可以看到进一步的测试。问题中的结果集是,如果按照我希望的方式运行,它应该返回什么。不是实际结果。在解决了这个问题之后,我认识到我可以简单地创建示例数据并对其进行测试。我已经这样做了,很快就会回答。你看过查询计划了吗?从你的结果中,我想你可以扣除总和将包括所有前面的行。否则,Id 1将不会有任何行,因为它将是负数。如果您将Sum列添加到视图中,并查看带过滤器和不带过滤器的结果,则可以看到进一步的测试。问题中的结果集是,如果按照我希望的方式运行,它应该返回什么。不是实际结果。在解决了这个问题之后,我认识到我可以简单地创建示例数据并对其进行测试。我已经做了,很快会回答。你看过查询计划了吗?