1

我有一个具有以下结构的表。

|anId|     aDate|aNumber|
-------------------------
|   1|2018-01-20|    100|
|   1|2019-01-01|   -100|
|   1|2019-02-01|     10|
|   2|2019-01-02|     40|

我有一个查询要在特定日期返回之前(包括)aNumber的 sum 是否> 0针对 each 。

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|

现在我已经把 query 变成了 view 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|

明年

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

应该返回

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

允许我将结果拼接在一起以获得原始的、未过滤的视图记录。


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

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

4

1 回答 1

0

创建这个问题后,我意识到它应该足够简单来测试它。

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);

使用子选择而不是创建实际视图

select
    *
from (
    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
    ) a
    where
      a.aSum > 0
) b
where
    b.aDate < '2019-01-01'
;

回报:

|anId|     aDate|aStatus|
-------------------------
|   1|2018-01-20|      1|

select
    *
from (
    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
    ) a
    where
      a.aSum > 0
) b
where
    b.aDate >= '2019-01-01'
;

回报:

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

这证实了日期过滤器不会影响总和。然而,这让我有些担心子查询是次优的,因为它可能在比必要的更多数据上运行总和。IE。当我想要 2018 年数据时,它还在计算 2019 年数据的总和吗?

于 2019-02-27T17:46:05.847 回答