在 CTE 中以日期为键插入“缺失记录”

问题描述 投票:0回答:2

我的 CTE 具有以下结构

ITEM,   DATE,       QUANTITY,   EXTRA
AAAA    01-07-2015  100         20
AAAA    04-07-2015  100         13
AAAA    07-07-2015  100         16
AAAA    09-07-2015  100         23
.
.
.
AAAA    31-07-2015  100         30

基本上,我想要做的是获取其中包含“缺失日期”的记录以及包含上一条记录中的 EXTRA 的 EXTRA 字段(如下所示)

ITEM,   DATE,       QUANTITY,   EXTRA
AAAA    01-07-2015  100         20
AAAA    02-07-2015  0           20
AAAA    03-07-2015  0           20
AAAA    04-07-2015  100         13
AAAA    05-07-2015  0           13
AAAA    06-07-2015  0           13
AAAA    07-07-2015  100         16
AAAA    08-07-2015  0           16
AAAA    09-07-2015  100         23
.
.
.
AAAA    31-07-2015  100         30

我可以使用 LAG 和包含有效日期完整列表 + MERGE 的临时表的组合来手动插入记录。然而,这个CTE只是用于一次性检查然后就被处理掉。有更好的办法吗?

sql-server tsql common-table-expression gaps-and-islands
2个回答
1
投票

试试这个;

;with tbl as (
    --your data....
),
max_min_val as (
  select max(date) as max_date, min(date) as min_date from tbl
),
all_date AS (
    SELECT min_date as DateColumn 
    from max_min_val
    UNION ALL
    SELECT DATEADD(day,1,DateColumn)
    FROM all_date, max_min_val
    WHERE DATEADD(day,1,DateColumn) <= max_date
)
select 
    coalesce(t.item, (select top 1 tt.item from tbl tt where tt.date < x.DateColumn order by tt.date desc)) as item,
    x.DateColumn as date, 
    coalesce(t.QUANTITY, 0) as QUANTITY,
    coalesce(t.EXTRA, (select top 1 tt.EXTRA from tbl tt where tt.date < x.DateColumn order by tt.date desc)) as EXTRA
from all_date x
left join
tbl t on t.date = x.DateColumn
  1. 这里
    all_date
    将包含
    date
    之间的所有
    min and max date in tbl
  2. 左连接
    all_date
    将给出所有日期
  3. coalesce(t.QUANTITY, 0) as QUANTITY
    将给出
    t.QUANTITY
    如果
    not null
    否则
    0
  4. EXTRA
    item
    将根据
    CTE tbl
    给出来自
    date
    的前几行数据。

1
投票

考虑以下因素:

我制作了一个

CTE
代表您的数据(不考虑
ITEM
,因为它在示例中不相关)。

通过以下两个

CTE
,我正在使用
data
搜索可用
recursive query
的最小和最大之间缺失的日期。

接下来,您需要将右侧的

data
连接到可用的
dates
。关键是从
date
中获取最大
data
的行,只要
data.date
小于
dates.date

最后,我根据示例的解释是,你想继承

extra
,但不继承
quantity
。因此
case
中的
select
语句。

with data as (
    select cast('2015-07-01' as date) date, 100 quantity, 20 extra union all
    select cast('2015-07-04' as date) date, 100 quantity, 13 extra union all
    select cast('2015-07-07' as date) date, 100 quantity, 16 extra union all
    select cast('2015-07-09' as date) date, 100 quantity, 23 extra
)

, maxDate as (
    select MAX(date) date
    from data
)

, dates as (
    select date
    from data

    union all

    select DATEADD(day,1,date) date
    from dates
    where DATEADD(day,1,date) not in (select date from data)
        and DATEADD(day,1,date) < (select date from maxDate)
)

select dates.date
, case dates.date when data.date then data.quantity else 0 end quantity
, data.extra
from dates
join data on data.date = (select max(date) from data where data.date <= dates.date)
order by 1
© www.soinside.com 2019 - 2024. All rights reserved.