sql 从一系列位值中生成几何序列
sql make geometric sequence from series of bit values
我有这个table:
declare @Table table (value int)
insert @Table select 0
insert @Table select 1
insert @Table select 1
insert @Table select 1
insert @Table select 0
insert @Table select 1
insert @Table select 1
现在,我需要进行 Select 查询,这将添加一列。一旦列值中有值1的系列,该列将构成一个几何序列。
这将是结果:
好的.. 首先,在数据库中,table 中的数据没有固有的排序。因此,为了做你想做的事,你需要在 sort/order 上创建一个字段。在本例中,我使用的是名为 'SortID'.
的 IDENTITY 字段
CREATE TABLE #Table (SortID int IDENTITY(1,1), BitValue bit);
INSERT INTO #Table (BitValue)
VALUES (0), (1), (1), (1), (0), (1), (1);
这给出了具有以下起始数据的 table
SortID BitValue
1 0
2 1
3 1
4 1
5 0
6 1
7 1
现在,解决问题
- 一种方法是通过递归 CTE - 当前行的值基于前几行的值。
- 但是,递归 CTE 可能存在性能问题(它们基本上是循环),因此最好尽可能采用基于集合的方法。
- 在这种情况下,因为你想要一个相关行号的2次方的几何序列,我们不需要前面的行来计算这一行——我们只需要知道行号
下面的做法
- 使用 CTE 创建一个名为 'GroupNum' 的新字段,用于将行分组在一起。每次一行的 BitValue 为 0 时,它都会将 GroupNum 递增 1。
- 在您的示例中,前四行将具有
GroupNum = 1
,其余三行将具有 GroupNum = 2
- 在上面使用 window 函数 - 按这些组编号进行分区,并在每个组中获得 row_number(减一)。
- 最终结果设置为变量
@a
对相关row_number的幂。
为了匹配您的示例,我使用 @a = 2
作为 POWER 函数的基础。
DECLARE @a int;
SET @a = 2;
WITH Grouped_BitValues AS
(SELECT SortID, BitValue,
CASE WHEN BitValue = 0 THEN 1 ELSE 0 END AS NewGrpFlag,
SUM(CASE WHEN BitValue = 0 THEN 1 ELSE 0 END) OVER (ORDER BY SortID) AS GroupNum
FROM #Table
)
SELECT BitValue, POWER(@a, ROW_NUMBER() OVER (PARTITION BY GroupNum ORDER BY SortID) -1) AS Geometric_Sequence
FROM Grouped_BitValues
ORDER BY SortID;
这是结果
BitValue Geometric_Sequence
0 1
1 2
1 4
1 8
0 1
1 2
1 4
请注意,在您的问题中,对于正确的几何序列,2^0 应该是 1,而不是 0。相反,如果您想要 0,则需要在 Geometric_Sequence 中编码以获得 CASE 表达式(例如,CASE WHEN BitValue = 0 THEN 0 ELSE POWER(...) AS Geometric_Sequence
)。
这里是 db<>fiddle 和
- 设置
- 答案
- 答案的组成部分(例如,CTE 和计算)以展示其计算方式
我将其表述为一道算术题。首先,您的问题表明行的顺序很重要。因此,您需要一列来指定排序。我假设有一个包含此信息的 id
列。
然后创建序列开始的组,对 0
进行累加和——所有 1
都在同一组中。给定数据,您可以将其表示为 sum(1 - value) over (order by id)
.
那就用算术吧:
select t.*,
value * power(2, row_number() over (partition by grp order by id) - 1) as generatedsequence
from (select t.*, sum(1 - value) over (order by id) as grp
from @table t
) t;
Here 是一个 db<>fiddle.
算术是要枚举组中的值,然后对 2 进行该次幂(除非 value
是 0
)。所以子查询 returns:
id. value grp
1 1 1
2 1 1
3 1 1
4 1 1
5 0 2
6 1 2
7 1 2
然后 row_number()
枚举每个 grp
.
中的值
我有这个table:
declare @Table table (value int)
insert @Table select 0
insert @Table select 1
insert @Table select 1
insert @Table select 1
insert @Table select 0
insert @Table select 1
insert @Table select 1
现在,我需要进行 Select 查询,这将添加一列。一旦列值中有值1的系列,该列将构成一个几何序列。
这将是结果:
好的.. 首先,在数据库中,table 中的数据没有固有的排序。因此,为了做你想做的事,你需要在 sort/order 上创建一个字段。在本例中,我使用的是名为 'SortID'.
的 IDENTITY 字段CREATE TABLE #Table (SortID int IDENTITY(1,1), BitValue bit);
INSERT INTO #Table (BitValue)
VALUES (0), (1), (1), (1), (0), (1), (1);
这给出了具有以下起始数据的 table
SortID BitValue
1 0
2 1
3 1
4 1
5 0
6 1
7 1
现在,解决问题
- 一种方法是通过递归 CTE - 当前行的值基于前几行的值。
- 但是,递归 CTE 可能存在性能问题(它们基本上是循环),因此最好尽可能采用基于集合的方法。
- 在这种情况下,因为你想要一个相关行号的2次方的几何序列,我们不需要前面的行来计算这一行——我们只需要知道行号
下面的做法
- 使用 CTE 创建一个名为 'GroupNum' 的新字段,用于将行分组在一起。每次一行的 BitValue 为 0 时,它都会将 GroupNum 递增 1。
- 在您的示例中,前四行将具有
GroupNum = 1
,其余三行将具有GroupNum = 2
- 在您的示例中,前四行将具有
- 在上面使用 window 函数 - 按这些组编号进行分区,并在每个组中获得 row_number(减一)。
- 最终结果设置为变量
@a
对相关row_number的幂。
为了匹配您的示例,我使用 @a = 2
作为 POWER 函数的基础。
DECLARE @a int;
SET @a = 2;
WITH Grouped_BitValues AS
(SELECT SortID, BitValue,
CASE WHEN BitValue = 0 THEN 1 ELSE 0 END AS NewGrpFlag,
SUM(CASE WHEN BitValue = 0 THEN 1 ELSE 0 END) OVER (ORDER BY SortID) AS GroupNum
FROM #Table
)
SELECT BitValue, POWER(@a, ROW_NUMBER() OVER (PARTITION BY GroupNum ORDER BY SortID) -1) AS Geometric_Sequence
FROM Grouped_BitValues
ORDER BY SortID;
这是结果
BitValue Geometric_Sequence
0 1
1 2
1 4
1 8
0 1
1 2
1 4
请注意,在您的问题中,对于正确的几何序列,2^0 应该是 1,而不是 0。相反,如果您想要 0,则需要在 Geometric_Sequence 中编码以获得 CASE 表达式(例如,CASE WHEN BitValue = 0 THEN 0 ELSE POWER(...) AS Geometric_Sequence
)。
这里是 db<>fiddle 和
- 设置
- 答案
- 答案的组成部分(例如,CTE 和计算)以展示其计算方式
我将其表述为一道算术题。首先,您的问题表明行的顺序很重要。因此,您需要一列来指定排序。我假设有一个包含此信息的 id
列。
然后创建序列开始的组,对 0
进行累加和——所有 1
都在同一组中。给定数据,您可以将其表示为 sum(1 - value) over (order by id)
.
那就用算术吧:
select t.*,
value * power(2, row_number() over (partition by grp order by id) - 1) as generatedsequence
from (select t.*, sum(1 - value) over (order by id) as grp
from @table t
) t;
Here 是一个 db<>fiddle.
算术是要枚举组中的值,然后对 2 进行该次幂(除非 value
是 0
)。所以子查询 returns:
id. value grp
1 1 1
2 1 1
3 1 1
4 1 1
5 0 2
6 1 2
7 1 2
然后 row_number()
枚举每个 grp
.