首页 > 解决方案 > 在按列分组的视图中添加日期范围

问题描述

我正在寻找一种解决方案,该解决方案允许我根据当前日期将日期范围(-1 周、当前周、+1 周;总共 3 周)设置为视图中的列。这个想法是将范围放在视图中,即使视图中没有相应的值。

示例值:

Current date: 2020-02-01
First day one week back: 2020-01-25
Last day one week forward: 2020-02-12

我来自哪里:

第 1 列 第 2 栏 第 3 栏 [待分组] 价值观
AAAAA 1001 A B C D 无效的
AAAAA 1001 EFGH 无效的
AAAAA 1001 IJKL 无效的
AAAAA 1001 MNOP 无效的
AAAAA 1001 QRST 无效的

我想去的地方:

第 1 列 第 2 栏 第 3 栏 [待分组] 日期 价值观
AAAAA 1001 A B C D 2020-01-25 无效的
AAAAA 1001 A B C D 2020-01-26 无效的
AAAAA 1001 A B C D 2020-01-27 无效的
AAAAA 1001 A B C D 2020-01-28 无效的
AAAAA 1001 A B C D 2020-01-29 无效的
AAAAA 1001 A B C D 2020-02-01 无效的
AAAAA 1001 A B C D 2020-02-02 无效的
AAAAA 1001 A B C D 2020-02-03 无效的
AAAAA 1001 A B C D 2020-02-04 无效的
AAAAA 1001 A B C D 2020-02-05 无效的
AAAAA 1001 A B C D 2020-02-08 无效的
AAAAA 1001 A B C D 2020-02-09 无效的
AAAAA 1001 A B C D 2020-02-10 无效的
AAAAA 1001 A B C D 2020-02-11 无效的
AAAAA 1001 A B C D 2020-02-12 无效的
AAAAA 1001 EFGH 2020-01-25 无效的
... ... ... ... ...
AAAAA 1001 EFGH 2020-02-12 无效的
AAAAA 1001 IJKL 2020-01-25 无效的
... ... ... ... ...
AAAAA 1001 IJKL 2020-02-12 无效的
... ... ... ... ...

所以即使没有值,我还是想显示日期。该视图应该是一个可立即使用的数据输入模式。

编辑:到目前为止,我尝试的是使用DATEADD()和定义所需的范围。我得到了我想要的输出作为单个选择语句,但未能将其添加到查询中。由于缺少值以及联合,无法与日历连接。我基本上想念的是像循环这样的迭代,但这是 SQL 的糟糕风格。

到目前为止的视图,因为我不知道如何解决日期值的所需状态:

CREATE view vDateAdd as 
with val as
select x.* from (
select *, row_number() over (
partition by Column 2, Dates order by Dates desc
) #row from sourcetable1) val
where a.#row = 1 )
) select Y.* from (
select 
sourcetable2.Column1, 
sourcetable2.Column2, 
sourcetable2.Column3, 
sourcetable3.Values 
from sourcetable2 
left join sourcetable3 
sourcetable2.Column3 on sourcetable3.Column3 
where Column2 IS NOT NULL
)Y

标签: sqlsql-serverdatetsqlview

解决方案


我会为此使用数字或计数表。有很多方法可以创建这种表并填充它,请谷歌或在 Stack Exchange 上搜索。在您有一个包含数字行的表格之后:1,2,3,4,5,6...10000 左右。您可以在此处使用该表(在下面的查询中称为 dbo.Numbers):

create table #weeks
(
    Column1 varchar(10),
    Column2 varchar(10),
    Column3 varchar(10)
)
insert into #weeks
select 'AAAAA','10001','abcd'
union all
select 'AAAAA','10001','efgh'
union all
select 'AAAAA','10001','ijkl'
union all
select 'AAAAA','10001','mnop'
union all
select 'AAAAA','10001','qrst' 

select 
    Column1, 
    Column2, 
    Column3, 
    case when n.Number > 21 --going into the fuuttuuureee... so return it to 1-21
        then dateadd(day,42-n.Number,getdate()) 
        else dateadd(day,-1*n.Number, getdate()) --going into the past, using 1-21, just go negative here so *-1
        end as DateColumn
from #weeks
cross join dbo.NUMBERS n
where 
    n.Number <= 42 --6 weeks total, 3 back, 3 forward 6*7 = 42
order by Column3, DateColumn

推荐阅读