我的数据类似于:
ID1 ID2 ID3 ID4
123 32 43 123
56 67 56 89
123 56 123 56
基本上描述了从ID1开始到ID4结束的序列。我感兴趣的只是提取模式,而不是涉及的ID。例如,第一行中的模式为:
ABCA:因为它从ID开始,转到新ID(B),然后是另一个新ID(C),然后回到原始ID(A)。
第二行是:ABAC
而第三个则是:ABAB。
我正在寻找一种有效的方法在sql server中执行此操作,而不是为每个潜在的情况使用大量的if语句。
答案 0 :(得分:3)
嗯。这是一种蛮力方法:
select 'A' +
(case when id2 = id1 then 'A' else 'B' end) +
(case when id3 = id1 then 'A'
when id3 = id2 then 'B'
when id2 = id1 then 'B'
else 'C'
end) +
(case when id4 = id1 then 'A'
when id4 = id2 then 'B'
when id4 = id3 and id2 = id1 then 'B'
when id3 = id2 then 'C'
when id2 = id1 then 'C'
else 'D'
end)
这有点复杂,但这样的事情应该有效。
编辑:
这是另一种应该起作用的方法:
select t.*, pattern
from t outer apply(
(select (max(case when id = 1 then val end) +
max(case when id = 2 then val end) +
max(case when id = 3 then val end) +
max(case when id = 4 then val end)
) pattern
from (select v.*,
char(ascii('A' + dense_rank() over (order by minpos) - 1)) as val
from (select v.*, min(pos) over (partition by id) as minpos
from (values(id1, 1), (id2, 2), (id3, 3), (id4, 4)) as v(id, pos)
) v
) v
) v;
解释这是如何工作的是一个相当大的挑战。 values()
命令将数据转换为行,因此第一行最终如下:
id pos
123 1
32 2
43 3
123 4
下一级将最小值置于找到值的位置:
id pos minpos
123 1 1
32 2 2
43 3 3
123 4 1
(注意:数字是连续的巧合。)
然后dense_rank()
将其变成字母:
id pos minpos val
123 1 1 A
32 2 2 B
43 3 3 C
123 4 1 A
最后的聚合将其置于ABCA模式中。