Sql Oracle select中使用窗口功能运行的总计(累积列)有什么问题?

Sql Oracle select中使用窗口功能运行的总计(累积列)有什么问题?,sql,oracle,window-functions,cumulative-sum,Sql,Oracle,Window Functions,Cumulative Sum,我有一个查询,在一列中包含0或1。出于演示目的,我将1替换为77,以便更容易看到: select dates.d the_date , case TO_CHAR(dates.d, 'd') when '7' then 0 when '1' then 0 else 77 end as is_workday from (SELECT (to_date('01.01.2019','dd.mm.yyyy') + (LEVEL -1)) AS d FROM DUAL conn

我有一个查询,在一列中包含
0
1
。出于演示目的,我将
1
替换为
77
,以便更容易看到:

select dates.d the_date
, case TO_CHAR(dates.d, 'd') when '7' then 0 when '1' then 0 
    else 77 
  end as is_workday
from (SELECT (to_date('01.01.2019','dd.mm.yyyy') + (LEVEL -1)) 
      AS d FROM DUAL connect by level <=( 
      to_date('31.12.2020','dd.mm.yyyy')-(to_date('01.01.2019','dd.mm.yyyy')))
     ) as dates
我想在
是_workday
的基础上添加一个运行总数,这意味着一个累积值。我确信Oracles的窗口功能就是为此而设计的

SELECT x.the_date
, x.is_workday
, sum(x.is_workday) over (
    partition by x.the_date          -- define the window
    order by x.the_date asc          -- order inside window
    rows between unbounded preceding -- sum to top
    and current row                  -- sum ending here
  ) as workdays_cumul
FROM (
  select dates.d the_date
  , case TO_CHAR(dates.d, 'd') when '7' then 0 when '1' then 0 
      else 77 
    end as is_workday
  from (SELECT (to_date('01.01.2019','dd.mm.yyyy') + (LEVEL -1)) 
        AS d FROM DUAL connect by level <=( 
        to_date('31.12.2020','dd.mm.yyyy')-(to_date('01.01.2019','dd.mm.yyyy')))
       ) as dates
) x
order by x.the_date
;
显然应该是:

| THE_DATE            | IS_WORKDAY | WORKDAYS_CUMUL |
| 2019-01-01 00:00:00 |  77        |   77           |
| 2019-01-02 00:00:00 |  77        |  154           |
| 2019-01-03 00:00:00 |  77        |  231           |
...
我以为会是这样的:

  • sum(x.is_workday)
    --对
    77
    -值进行求和
  • 按x.the_日期进行分区
    ——每个窗口/部分/部件各有一行(在我的例子中)
  • 按x排序。日期asc
    ——按日期排序这些行
  • 无界前一行之间的行
    --第一行之间的和
  • 和当前行
    --。。。和当前行

我在这里遗漏了什么?

删除查询中的
PARTITION BY
子句,因为窗口的作用域是整个查询,而不是每个单独的日期:

SELECT the_date
,      is_workday
,      sum(is_workday) over (
         ORDER BY the_date asc            -- order inside window
         ROWS BETWEEN unbounded preceding -- sum to top
                  AND current row         -- sum ending here
       ) as workdays_cumul
FROM (
  select d the_date
  ,      CASE
         WHEN d - TRUNC( d, 'IW' ) IN ( 5, 6 )
         THEN 0
         ELSE 1 
         END AS is_workday
  FROM (
    SELECT DATE '2019-01-01' + LEVEL -1 AS d
    FROM   DUAL
    connect by level <= DATE '2020-12-31' - DATE '2019-01-01'
  )
)
order by the_date;

dbfiddle

按日期划分将每个日期的值相加(基本上按日期分组)。移除它。@JohnHC ohh。。。。所以我必须定义“一个大窗口”而不是“许多小窗口”。。。我懂了!替换为
按x按1顺序分区。日期asc
似乎做到了这一点!谢谢,你可以回答这个问题。
按1分区是否是“删除它”的正确方式?与您的问题无关,但
to_CHAR(dates.d,'d')
是;例如,在英国和美国,你会得到不同的答案,因为一周从不同的日子开始。@AlexPoole谢谢。我确实用
J
MOD 7
找到了一个解决方案,我想知道这是为什么。我希望oracle能在他们的文档中提到这一点,格式为
D
实际上,默认情况下,
前一行和当前行之间的行是无界的
,因此您可以简单地将
总和(x.is\u workday)写入(按x.u日期排序)
| THE_DATE            | IS_WORKDAY | WORKDAYS_CUMUL |
| 2019-01-01 00:00:00 |  77        |   77           |
| 2019-01-02 00:00:00 |  77        |  154           |
| 2019-01-03 00:00:00 |  77        |  231           |
...
SELECT the_date
,      is_workday
,      sum(is_workday) over (
         ORDER BY the_date asc            -- order inside window
         ROWS BETWEEN unbounded preceding -- sum to top
                  AND current row         -- sum ending here
       ) as workdays_cumul
FROM (
  select d the_date
  ,      CASE
         WHEN d - TRUNC( d, 'IW' ) IN ( 5, 6 )
         THEN 0
         ELSE 1 
         END AS is_workday
  FROM (
    SELECT DATE '2019-01-01' + LEVEL -1 AS d
    FROM   DUAL
    connect by level <= DATE '2020-12-31' - DATE '2019-01-01'
  )
)
order by the_date;
THE_DATE | IS_WORKDAY | WORKDAYS_CUMUL :-------- | ---------: | -------------: 01-JAN-19 | 1 | 1 02-JAN-19 | 1 | 2 03-JAN-19 | 1 | 3 04-JAN-19 | 1 | 4 05-JAN-19 | 0 | 4 06-JAN-19 | 0 | 4 07-JAN-19 | 1 | 5 08-JAN-19 | 1 | 6 09-JAN-19 | 1 | 7 ... 24-DEC-20 | 1 | 518 25-DEC-20 | 1 | 519 26-DEC-20 | 0 | 519 27-DEC-20 | 0 | 519 28-DEC-20 | 1 | 520 29-DEC-20 | 1 | 521 30-DEC-20 | 1 | 522