sql - T-SQL 查询 - 无游标的行迭代

标签 sql sql-server tsql

我有一张 table

T (variable_name, start_no, end_no) 

包含如下值:

(x, 10, 20)
(x, 30, 50)
(x, 60, 70)
(y, 1, 3)
(y, 7, 8)

保证所有间隔都是不相交的。

我想在 T-SQL 中编写一个查询来计算不搜索变量的时间间隔:

(x, 21, 29)
(x, 51, 59)
(y, 4, 6)

我可以在没有光标的情况下执行此操作吗?

我正在考虑按variable_name分区,然后按start_no排序。但接下来如何进行呢?给定行集中的当前行,如何访问“下一个”行?

最佳答案

由于您没有指定 SQL Server 的版本,所以我有多种解决方案。如果您仍在使用 SQL Server 2005,那么 Giorgi 的 CROSS APPLY 的使用效果非常好。

注意:对于这两种解决方案,我使用 where 子句来过滤掉不正确的值,因此即使数据错误并且行重叠,它也会忽略这些值。

我的 table 版本

DECLARE @T TABLE (variable_name CHAR, start_no INT, end_no INT) 
INSERT INTO @T
VALUES  ('x', 10, 20),
        ('x', 30, 50),
        ('x', 60, 70),
        ('y', 1, 3),
        ('y', 7, 8);

SQL Server 2012 及更高版本的解决方案

SELECT *
FROM
(
    SELECT  variable_name,
            LAG(end_no,1) OVER (PARTITION BY variable_name ORDER BY start_no) + 1 AS start_range,
            start_no - 1 AS end_range
    FROM @T
) A
WHERE end_range > start_range

SQL 2008及以上版本的解决方案

WITH CTE
AS
(
    SELECT  ROW_NUMBER() OVER (PARTITION BY variable_name ORDER BY start_no) row_num,
            *
    FROM @T
)

SELECT  A.variable_name,
        B.end_no + 1 AS start_range,
        A.start_no - 1 AS end_range
FROM CTE AS A
INNER JOIN CTE AS B
ON      A.variable_name = B.variable_name
    AND A.row_num = B.row_num + 1
WHERE A.start_no - 1 /*end_range*/ > B.end_no + 1 /*start_range*/

关于sql - T-SQL 查询 - 无游标的行迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30871239/

相关文章:

SQL Server错误: the multi-part identifier "C.Name" could not be bound

c# - 由于索引超出范围,无法设置列标题文本

SQL- UNION ALL 大量表

sql-server - 在 MS SQL Server 2005 中获取日期的周数?

sql - 如何在 MS SQL Server 上模拟 Oracle 物化 View ?

sql - "Must declare the scalar variable"执行存储过程时出错

mysql - MySQL 中 UNION 附近的语法错误?

c# - 计算用户排名

sql-server - 覆盖 SSDT 发布配置文件 ConnectionString

c# - 将远程 SQL Server 数据库与本地 SQL Server Compact 数据库同步的最佳方法?