Sql 从数字序列中获取非更改值的间隔
我需要将一系列值汇总为非变化值的区间——每个区间的开始、结束和值。我可以很容易地用plsql实现这一点,但出于性能和教育方面的原因,我想要一个纯sql解决方案。一段时间以来,我一直在尝试用分析函数来解决这个问题,但不知道如何正确定义windowing子句。我遇到的问题是重复值 简化示例- 给定输入:Sql 从数字序列中获取非更改值的间隔,sql,oracle,Sql,Oracle,我需要将一系列值汇总为非变化值的区间——每个区间的开始、结束和值。我可以很容易地用plsql实现这一点,但出于性能和教育方面的原因,我想要一个纯sql解决方案。一段时间以来,我一直在尝试用分析函数来解决这个问题,但不知道如何正确定义windowing子句。我遇到的问题是重复值 简化示例- 给定输入: id value 1 1 2 1 3 2 4 2 5 1 我想得到输出 from to val 1 2 1 3 4 2 5 5 1 您希望标识
id value
1 1
2 1
3 2
4 2
5 1
我想得到输出
from to val
1 2 1
3 4 2
5 5 1
您希望标识相邻值的组。一种方法是使用
lag()
另一种方法是行号的差异:
select value, min(id) as from_id, max(id) as to_id
from (select t.*,
(row_number() over (order by id) -
row_number() over (partition by val order by id
) as grp
from table t
) t
group by grp, value;
您希望标识相邻值的组。一种方法是使用lag()
另一种方法是行号的差异:
select value, min(id) as from_id, max(id) as to_id
from (select t.*,
(row_number() over (order by id) -
row_number() over (partition by val order by id
) as grp
from table t
) t
group by grp, value;
您希望标识相邻值的组。一种方法是使用lag()
另一种方法是行号的差异:
select value, min(id) as from_id, max(id) as to_id
from (select t.*,
(row_number() over (order by id) -
row_number() over (partition by val order by id
) as grp
from table t
) t
group by grp, value;
您希望标识相邻值的组。一种方法是使用lag()
另一种方法是行号的差异:
select value, min(id) as from_id, max(id) as to_id
from (select t.*,
(row_number() over (order by id) -
row_number() over (partition by val order by id
) as grp
from table t
) t
group by grp, value;
使用CTE收集所有行并将它们标识为变化的值,最后将这些变化的值分组在一起
CREATE TABLE #temp (
ID INT NOT NULL IDENTITY(1,1),
[Value] INT NOT NULL
)
GO
INSERT INTO #temp ([Value])
SELECT 1 UNION ALL
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 2 UNION ALL
SELECT 1;
WITH Marked AS (
SELECT
*,
grp = ROW_NUMBER() OVER (ORDER BY ID)
- ROW_NUMBER() OVER (PARTITION BY Value ORDER BY ID)
FROM #temp
)
SELECT MIN(ID) AS [From], MAX(ID) AS [To], [VALUE]
FROM Marked
GROUP BY grp, Value
ORDER BY MIN(ID)
DROP TABLE #temp;
使用CTE收集所有行并将它们标识为变化的值,最后将这些变化的值分组在一起
CREATE TABLE #temp (
ID INT NOT NULL IDENTITY(1,1),
[Value] INT NOT NULL
)
GO
INSERT INTO #temp ([Value])
SELECT 1 UNION ALL
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 2 UNION ALL
SELECT 1;
WITH Marked AS (
SELECT
*,
grp = ROW_NUMBER() OVER (ORDER BY ID)
- ROW_NUMBER() OVER (PARTITION BY Value ORDER BY ID)
FROM #temp
)
SELECT MIN(ID) AS [From], MAX(ID) AS [To], [VALUE]
FROM Marked
GROUP BY grp, Value
ORDER BY MIN(ID)
DROP TABLE #temp;
使用CTE收集所有行并将它们标识为变化的值,最后将这些变化的值分组在一起
CREATE TABLE #temp (
ID INT NOT NULL IDENTITY(1,1),
[Value] INT NOT NULL
)
GO
INSERT INTO #temp ([Value])
SELECT 1 UNION ALL
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 2 UNION ALL
SELECT 1;
WITH Marked AS (
SELECT
*,
grp = ROW_NUMBER() OVER (ORDER BY ID)
- ROW_NUMBER() OVER (PARTITION BY Value ORDER BY ID)
FROM #temp
)
SELECT MIN(ID) AS [From], MAX(ID) AS [To], [VALUE]
FROM Marked
GROUP BY grp, Value
ORDER BY MIN(ID)
DROP TABLE #temp;
使用CTE收集所有行并将它们标识为变化的值,最后将这些变化的值分组在一起
CREATE TABLE #temp (
ID INT NOT NULL IDENTITY(1,1),
[Value] INT NOT NULL
)
GO
INSERT INTO #temp ([Value])
SELECT 1 UNION ALL
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 2 UNION ALL
SELECT 1;
WITH Marked AS (
SELECT
*,
grp = ROW_NUMBER() OVER (ORDER BY ID)
- ROW_NUMBER() OVER (PARTITION BY Value ORDER BY ID)
FROM #temp
)
SELECT MIN(ID) AS [From], MAX(ID) AS [To], [VALUE]
FROM Marked
GROUP BY grp, Value
ORDER BY MIN(ID)
DROP TABLE #temp;
这不是有效的Oracle语法(看起来像SQL Server)。@FrankSchmitt oops你是对的。只是刚刚注意到标记是orcale和sql(不是sql server),这是无效的Oracle语法(看起来像sql server)。@FrankSchmitt oops你说得对。只是刚刚注意到标记是orcale和sql(不是sql server),这是无效的Oracle语法(看起来像sql server)。@FrankSchmitt oops你说得对。只是刚刚注意到标记是orcale和sql(不是sql server),这是无效的Oracle语法(看起来像sql server)。@FrankSchmitt oops你说得对。只是刚刚注意到标签是orcale和sql(不是sql server),我猜lag/lead会有帮助,但这对第一行/最后一行有额外的工作,“本质上”是一个过程解决方案。您使用rownumber来区分相同值的非相邻组的“技巧”非常好。今天我学到了一些东西:-)。我猜滞后/超前会有帮助,但这对第一行/最后一行有额外的工作,而且“本质上”是一个程序性的解决方案。您使用rownumber来区分相同值的非相邻组的“技巧”非常好。今天我学到了一些东西:-)。我猜滞后/超前会有帮助,但这对第一行/最后一行有额外的工作,而且“本质上”是一个程序性的解决方案。您使用rownumber来区分相同值的非相邻组的“技巧”非常好。今天我学到了一些东西:-)。我猜滞后/超前会有帮助,但这对第一行/最后一行有额外的工作,而且“本质上”是一个程序性的解决方案。您使用rownumber来区分相同值的非相邻组的“技巧”非常好。今天我学到了一些东西:-)。