SQL查询通过int变量返回1

时间:2009-05-06 22:12:40

标签: sql sql-server

在SQL Server中,如果我有一个int变量,如何编写一个通过int变量的值返回值1的查询?

所以给出:

declare @cnt int
set @cnt = 5

什么查询会返回1 - 5?这可能吗?

10 个答案:

答案 0 :(得分:5)

已经给出的其他人的替代答案,可能不那么实用,但在某些情况下可能更快。

如果你有一个已知的@cnt值的上限你会遇到(比如1000)你可以创建一个简单的单列表,其中包含前1000个整数,比如

val
---
1
2
3
4
...

然后,只要你想要一组整数,就可以使用

获得它
select val
from integerTable
where val <= @cnt

答案 1 :(得分:4)

您可以在SQL中执行 WHILE 循环,如下所示:

DECLARE @Cnt int, 
        @Val int;
SET @Cnt = 5;
SET @Val = 0;

DECLARE @MyValues TABLE
(
  val int
);

WHILE @Val < @Cnt
 BEGIN
  SET @Val = @Val + 1;
  INSERT @MyValues(val)
  SELECT @Val;
 END;
SELECT Val FROM @MyValues;

答案 2 :(得分:2)

您可以使用recursive CTE在一个查询中执行此操作,但如果您的@cnt以非常高的值启动,则需要注意MAXRECURSION查询提示。

DECLARE @cnt int;
SET @cnt = 5;

WITH Numbers AS (
    SELECT @cnt [Value]

    UNION ALL

    SELECT [Value] - 1
    FROM Numbers
    WHERE [Value] > 1
)
SELECT * FROM Numbers
ORDER BY [Value]

尽管如此,使用简单的WHILE循环进行操作会更简单,更容易阅读。

答案 3 :(得分:1)

您只需在查询结尾处使用SELECT语句即可轻松实现“输出”值...

SELECT ... FROM ... WHERE ... Bla Bla, yadah, yadah;
SELECT (1 - @cnt);

您将获得所需的输出。

答案 4 :(得分:1)

这是一个执行此操作的功能:

CREATE FUNCTION [dbo].[Sequence] (@start int, @end int, @step int)  
RETURNS @result table (num int) AS  
BEGIN 
    declare @num int
    set @num = @start

    while @num <= @end
        begin
        insert into @result (num) values (@num)
        set @num = @num + @step
        end
    return
END

使用此功能,您可以选择以下序列:

select * from dbo.Sequence(1,5,1)

返回1,2,3,4,5。

select * from dbo.Sequence(2,6,2)

将返回2,4,6。等等:)

答案 5 :(得分:1)

如果上下文中@cnt的最大值相对较低,则可以填充临时或持久的整数表,并从中选择或加入。

CREATE TABLE LotsOfNumbers(Number int not null)
INSERT INTO LotsOfNumbers VALUES(1)
INSERT INTO LotsOfNumbers VALUES(2)
INSERT INTO LotsOfNumbers VALUES(3)
...
INSERT INTO LotsOfNumbers VALUES(99)
INSERT INTO LotsOfNumbers VALUES(100)


DECLARE @cnt INT
SET @cnt = 30

SELECT *
FROM LotsOfNumbers
WHERE Number <= @cnt
ORDER BY Number

当然,时间/空间性能取决于您的情况,因此我会观察SQL事件探查器以了解每种方法对数据库的命中。

答案 6 :(得分:0)

declare @cnt int
    set @cnt = 0
    while @cnt < 5
    begin
      set @cnt = @cnt + 1
      print 'The counter is ' + cast(@counter as char)
    end

答案 7 :(得分:0)

不知道您是否只想要一个结果集(根据José Basilio's answer)或者对多个结果感到满意

DECLARE @ctr INT
DECLARE @start INT

SET @ctr = 5
SET @start = 1

WHILE @start <= @ctr
BEGIN
   SELECT @start
   SET @start = @start + 1
END

答案 8 :(得分:0)

使用数字生成单列表很容易。

Create Table Numbers(Number INT);

INSERT INTO Numbers(Number) values(0);
INSERT INTO Numbers(Number) values(1);
INSERT INTO Numbers(Number) values(2);
.
.
INSERT INTO Numbers(Number) values(9);

-- To generate a list of 100000

SELECT * INTO TEST
FROM
(SELECT N1.Number * 1000 +  N2.Number * 100 + N3.Number * 10 + N4.Number * 1 as Num
FROM   Numbers N1
CROSS JOIN Numbers N2
CROSS JOIN Numbers N3
CROSS JOIN Numbers N4) AS N
ORDER BY Num;

--Then, You can use the above table for getting the numbers
SELECT * from TEST WHERE Num <= 5;

答案 9 :(得分:0)

我不得不在几年前处理这个问题,所以如果你的数据库有一个比你需要计算更多记录的表,我想出了最快/最简单的方法。

首先,尽管建议您不需要“创建”记录表...您只需要“ANY”表已经有记录。只要表中记录的记录多于您需要的记录,那么您就是好的。

SELECT top (5) ROW_NUMBER() OVER(Order by [Primary_Key] desc) AS Integer 
FROM SOME_TABLE   --that has more than 5 rows.

这也是优雅的(数学)方式。数据库中已有大表的地方。

使用Split递归,这允许您生成一个最多包含2 ^ n-1个整数的表,其中n是递归限制。此外,这是完全参数化的,因此可以轻松地将其放入函数

DECLARE @n int, @cnt int;
set @cnt = 5;
SET @n = LOG(@cnt)/LOG(2) +1; --use change of base to find LOG base 2

WITH Num AS (
    SELECT @n [Value]
    UNION ALL

    SELECT [Value] - 1
    FROM Num
    WHERE [Value] > 1 

    UNION ALL

    SELECT [Value] - 1
    FROM Num
    WHERE [Value] > 1
) 

SELECT * from (
SELECT ROW_NUMBER() OVER(Order by Value asc) AS [Integer]
FROM Num
)i 
where [Integer] <= @cnt

这样做的一个缺点是它在递归期间可以生成最多两倍的记录,因此它有可能比内联递归产生更多的开销。但由于这一点,完全避免了递归限制。 (你不应该需要列出前2 ^ 100-1个整数。)(我也只是预测你没有那么多硬盘空间的计算机。)

这个缺点是我创建下一个功能的原因。它使用与分割递归相同的倍增技术但在while循环内。并且它最后一次运行它只会使必要的记录不加倍。此功能还允许您指定范围并返回该范围内的所有数字,并使用这些数字的0索引。我曾经认为零基本列是计算中无用的工件,但是将范围及其索引放在一行中非常有帮助。

create   function [dbo].[fn_Integers] 
(
@Min_Integer  int = 1
,@Max_Integer int 
)
RETURNS @retTable TABLE 
    ([BASE]  int identity(0,1)
    ,[INTEGER] int) 
AS
BEGIN
    Declare @RANGE int
    SET @RANGE = @Max_Integer-@Min_Integer

    insert into @retTable
    select NULL --initial value for recursion

    While ((SELECT MAX([BASE]) FROM @retTable r) < @RANGE )
    BEGIN
        INSERT into @retTable
        select [INTEGER] from @retTable r
        where [BASE] < (SELECT @RANGE - MAX([BASE])  FROM @retTable r)
    END

    Update @retTable set
    [INTEGER] = [BASE] + @Min_Integer

RETURN
END
GO

它每秒可以做大约50000个整数(在我的工作站上) 和输出看起来像

SELECT * FROM [fn_Integers](18,50000)

BASE    INTEGER
-----------------
0       18
1       19
2       20
...
49982   50000