Cursor 中的 BETWEEN 查询未返回所有行 SQL
BETWEEN query within Cursor not returning all rows SQL
我写了一个嵌套的游标语句,目的是:
1. 遍历 2 列 table 并使用第一列作为范围开始,第二列作为范围结束
2. return 单独 table 中所有值的 1 列 table 在范围内(含)
我的问题是 table 中未包含范围结束值。
@RangeTable:
range1 range2
--------------------
A03 A069
A20 A20
A202 A202
A25 A25
A250 A2509
A251 A251
A2511 A2513
A254 A2549
A263 A2651
------------------
以下是创建 table 的代码,其中包含所有值范围内的所有产品 ID。这些值采用 varchar 格式。当我查询原始 table [dbo].[products] 使用时,即
BETWEEN A03 and A069
甚至一个值范围,例如
BETWEEN 'A25' AND 'A25'
我得到了我需要的一切。
Select DISTINCT * into #temp From @RangeTable
DECLARE @prodID varchar(20);
DECLARE @rangestart varchar(20);
DECLARE @rangeend varchar(20);
DECLARE @prods TABLE (ID VARCHAR(32));
DECLARE ranges CURSOR FOR
SELECT RangeFrom, RangeTo FROM #temp
OPEN ranges
FETCH NEXT FROM ranges
INTO @rangestart, @rangeend
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE id CURSOR FOR
SELECT c.ID
FROM dbo.products as c
WHERE rtrim(ltrim(c.ID)) BETWEEN rtrim(ltrim(@rangestart)) AND rtrim(ltrim(@rangeend))
ORDER BY c.ID;
OPEN id
FETCH NEXT FROM id INTO @prodID
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO @prods VALUES(@prodID)
FETCH NEXT FROM id INTO @prodID
END
CLOSE id;
DEALLOCATE id;
FETCH NEXT FROM ranges INTO @rangestart, @rangeend
END
CLOSE ranges;
DEALLOCATE ranges;
SELECT * FROM @prods
TRUNCATE TABLE #temp
DROP TABLE #temp
它不包括范围 2 中的值,并且对于一个值范围(即 'A20' 到 'A20'),它会完全跳过它。
我尝试过以其他方式使用 FETCH,例如将 CURSOR 设置为 SCROLL 并使用 FETCH LAST,但即使这样 return 也是范围内的倒数第二个值。
起初我认为这可能是一个尾随空白问题,这就是我放入 rtrim 和 ltrim 的原因。
当我调试时,我可以看到 @@FETCH_STATUS 更改为 -1 跟随该范围内倒数第二个值。
提前感谢您的任何想法、提示或建议。
你必须拥有所有这些吗?
WHERE rtrim(ltrim(c.ID)) BETWEEN rtrim(ltrim(@rangestart)) AND rtrim(ltrim(@rangeend))
为什么不呢?
WHERE c.ID BETWEEN @rangestart AND @rangeend
而且,你试过了吗:
WHERE c.ID >= @rangestart AND c.ID <= @rangeend
要获得您正在寻找的结果?
为什么要使用游标? SQL 在处理集合时最有效。因为您没有为每一行做任何特别的事情。因此,设置处理似乎会更有效。当您必须单独处理每条记录时,最好使用游标。例如,您不知道数据的质量是否足够,您必须将出错的记录写到单独的文件中进行处理。 (甚至可以使用基于多个集合的查询来完成...)
示例:http://sqlfiddle.com/#!3/41bf9/1/0
在示例中,我只是根据范围之间的数据加入数据,然后将您的产品 ID 插入新的 table "B"
SELECT P.ID into B
FROM products P
INNER JOIN Ranges R
on P.ID between R.Range1 and R.Range2;
请注意,在我的示例中,A250 和 A2509 将不包括 A251
我写了一个嵌套的游标语句,目的是: 1. 遍历 2 列 table 并使用第一列作为范围开始,第二列作为范围结束 2. return 单独 table 中所有值的 1 列 table 在范围内(含)
我的问题是 table 中未包含范围结束值。
@RangeTable:
range1 range2
--------------------
A03 A069
A20 A20
A202 A202
A25 A25
A250 A2509
A251 A251
A2511 A2513
A254 A2549
A263 A2651
------------------
以下是创建 table 的代码,其中包含所有值范围内的所有产品 ID。这些值采用 varchar 格式。当我查询原始 table [dbo].[products] 使用时,即
BETWEEN A03 and A069
甚至一个值范围,例如
BETWEEN 'A25' AND 'A25'
我得到了我需要的一切。
Select DISTINCT * into #temp From @RangeTable
DECLARE @prodID varchar(20);
DECLARE @rangestart varchar(20);
DECLARE @rangeend varchar(20);
DECLARE @prods TABLE (ID VARCHAR(32));
DECLARE ranges CURSOR FOR
SELECT RangeFrom, RangeTo FROM #temp
OPEN ranges
FETCH NEXT FROM ranges
INTO @rangestart, @rangeend
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE id CURSOR FOR
SELECT c.ID
FROM dbo.products as c
WHERE rtrim(ltrim(c.ID)) BETWEEN rtrim(ltrim(@rangestart)) AND rtrim(ltrim(@rangeend))
ORDER BY c.ID;
OPEN id
FETCH NEXT FROM id INTO @prodID
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO @prods VALUES(@prodID)
FETCH NEXT FROM id INTO @prodID
END
CLOSE id;
DEALLOCATE id;
FETCH NEXT FROM ranges INTO @rangestart, @rangeend
END
CLOSE ranges;
DEALLOCATE ranges;
SELECT * FROM @prods
TRUNCATE TABLE #temp
DROP TABLE #temp
它不包括范围 2 中的值,并且对于一个值范围(即 'A20' 到 'A20'),它会完全跳过它。
我尝试过以其他方式使用 FETCH,例如将 CURSOR 设置为 SCROLL 并使用 FETCH LAST,但即使这样 return 也是范围内的倒数第二个值。
起初我认为这可能是一个尾随空白问题,这就是我放入 rtrim 和 ltrim 的原因。 当我调试时,我可以看到 @@FETCH_STATUS 更改为 -1 跟随该范围内倒数第二个值。
提前感谢您的任何想法、提示或建议。
你必须拥有所有这些吗?
WHERE rtrim(ltrim(c.ID)) BETWEEN rtrim(ltrim(@rangestart)) AND rtrim(ltrim(@rangeend))
为什么不呢?
WHERE c.ID BETWEEN @rangestart AND @rangeend
而且,你试过了吗:
WHERE c.ID >= @rangestart AND c.ID <= @rangeend
要获得您正在寻找的结果?
为什么要使用游标? SQL 在处理集合时最有效。因为您没有为每一行做任何特别的事情。因此,设置处理似乎会更有效。当您必须单独处理每条记录时,最好使用游标。例如,您不知道数据的质量是否足够,您必须将出错的记录写到单独的文件中进行处理。 (甚至可以使用基于多个集合的查询来完成...)
示例:http://sqlfiddle.com/#!3/41bf9/1/0
在示例中,我只是根据范围之间的数据加入数据,然后将您的产品 ID 插入新的 table "B"
SELECT P.ID into B
FROM products P
INNER JOIN Ranges R
on P.ID between R.Range1 and R.Range2;
请注意,在我的示例中,A250 和 A2509 将不包括 A251