我的数据类似于:
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 语句。
最佳答案
嗯。这是一个暴力方法:
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 中。
关于sql - 从 SQL Server 中的列派生序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39564215/