我正在创建来自多个供应商的导入数据工具。不幸的是,数据不是我生成的,所以我必须使用它。我遇到过以下情况。
我有一个如下表:
ID |SartDate |Availability
========================================
H1 |20130728 |YYYYYYNNNNQQQQQ
H2 |20130728 |NNNNYYYYYYY
A3 |20130728 |NNQQQQNNNNNNNNYYYYYY
A2 |20130728 |NNNNNYYYYYYNNNNNN
解释一下这个数据的含义是: Availability 列中的每个字母都是特定日期的可用性标志,从 StartDate 列中注明的日期开始。
- 是:可用
- N:不可用
- 问:根据要求
例如,ID H1 20130728 - 20130802 可用,则 20130803 - 20130806 不可用,而 20130807 - 20130811 可根据要求提供。
我需要做的就是将此表转换为以下设置:
ID |Available |SartDate |EndDate
========================================
H1 |Y |20130728 |20130802
H1 |N |20130803 |20130806
H1 |Q |20130806 |20130811
H2 |N |20130728 |20130731
H2 |Y |20130801 |20130807
A3 |N |20130728 |20130729
A3 |Q |20130730 |20130802
A3 |N |20130803 |20130810
A3 |Y |20130811 |20130816
A2 |Y |20130728 |20130801
A2 |Y |20130802 |20130807
A2 |Y |20130808 |20130813
初始表大约有 40,000 行。 Availability 列可能有几天(我见过最多 800 天)。
我尝试过的是将可用性转换为行,然后将连续的天分组在一起,然后获取每组的最小和最大日期。为此,我使用了三四个 CTE
这对于一些 ID 来说效果很好,但是当我尝试将它应用到整个表时,它需要很长时间(我在傻瓜时间 sleep 后停止了初始测试运行,它还没有完成,是的,我的意思是我是运行时 sleep !!!)
我估计,如果我将每个字符转为一行,那么我最终会得到大约 1450 万行。
所以,我想问,有没有更有效的方法来做到这一点? (我知道有,但我需要你告诉我)
提前致谢。
最佳答案
这可以在 SQL Server 中使用递归 CTE 来完成。这是一个例子:
with t as (
select 'H1' as id, cast('20130728' as date) as StartDate,
'YYYYYYNNNNQQQQQ' as Availability union all
select 'H2' as id, cast('20130728' as date) as StartDate,
'NNNNYYYYYYY' as Availability union all
select 'H3' as id, cast('20130728' as date) as StartDate,
'NQ' as Availability
),
cte as (
select id, left(Availability, 1) as Available,
StartDate as thedate,
substring(Availability, 2, 1000) as RestAvailability,
1 as i,
1 as periodcnt
from t
union all
select t.id, left(RestAvailability, 1),
dateadd(dd, 1, thedate),
substring(RestAvailability, 2, 1000) as RestAvailability,
1 + cte.i,
(case when substring(t.Availability, i, 1) = substring(t.Availability, i+1, 1)
then periodcnt
else periodcnt + 1
end)
from t join
cte
on t.id = cte.id
where len(RestAvailability) > 0
)
select id, min(thedate), max(thedate), Available
from cte
group by id, periodcnt, Available;
其工作方式是首先分散日期。这将是 CTE 的“典型”用途。在此过程中,它还会跟踪 Available
是否较之前的值发生更改(在变量 periodcnt
中)。它为此使用字符串操作。
有了这些信息,最终结果就是这个 CTE 的聚合。
关于sql - varchar字段的分组字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17943169/