sql - 从 SQL Server 中的列派生序列

标签 sql sql-server

我的数据类似于:

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/

相关文章:

php - MySQL 双等号

sql - plsql - 获取第一行 - 哪个更好?

SQL 按偏移日期范围分组

sql-server - 查找SQL记录中的并发用户数

sql-server - SQL Server中ISNULL(SUM(x),0)或SUM(ISNULL(x,0)之间的差异

mysql - 在不使用自连接的情况下显示详细信息

SQL Server - 查询短路?

mysql - sql NOW() 并返回用户实际时区?

sql - 在 SELECT 语句中填写缺失值

sql - 澄清为什么 EXECUTE AS USER/LOGIN 没有返回预期结果?