返回最多为设定值的数字列表

时间:2012-06-13 17:35:04

标签: sql sql-server tsql

我见过以下用于返回数字列表

SELECT TOP (SELECT MAX(Quantity) FROM @d) 
       rn = ROW_NUMBER() OVER (ORDER BY object_id)    
FROM   sys.all_columns 
ORDER BY object_id  

如果最大数量为5,那么我假设以上回报:

rn
1
2
3
4
5

有更优雅的方式返回这个数字列表吗?

6 个答案:

答案 0 :(得分:7)

你可以这样做:

SELECT        rn = 1 
  UNION ALL SELECT 2 
  UNION ALL SELECT 3 
  UNION ALL SELECT 4 
  UNION ALL SELECT 5;

当数字为5但不是50或5000时,这是可以容忍的。当你需要更多时,你可以做一些事情,比如使用CTE建立一组数字然后交叉连接来爆炸集合(你可以看到一个几个例子here, under Inline 1 / Inline 2)。

或者您可以建立一个数字表格,假设您可能需要5个或者您可能需要一百万个:

SET NOCOUNT ON;

DECLARE @UpperLimit INT = 1000000;

WITH n AS
(
    SELECT
        x = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
    FROM       sys.all_objects AS s1
    CROSS JOIN sys.all_objects AS s2
    CROSS JOIN sys.all_objects AS s3
)
SELECT Number = x
  INTO dbo.Numbers
  FROM n
  WHERE x BETWEEN 1 AND @UpperLimit;

GO
CREATE UNIQUE CLUSTERED INDEX n ON dbo.Numbers(Number);
GO

然后当你想要一些数字时,你只需说:

SELECT TOP (5) rn = Number 
  FROM dbo.Numbers 
  ORDER BY Number;

显然,使用sys.all_columns或任何具有足够行的内置对象可以避免创建Numbers表的前期步骤(无论如何,许多人都反对这一点)。

现在,如果更优雅的方式来做这件事会非常好,不是吗?你不会在任何当前版本中看到它,但我们有可能在未来的版本中看到它。请在这里投票(更重要的是,评论你的用例):

http://connect.microsoft.com/SQLServer/feedback/details/258733/add-a-built-in-table-of-numbers

答案 1 :(得分:2)

我过去曾经使用过这样的东西 - 尽管它只能达到100左右:

WITH Numbers(number) AS (
SELECT 1 number
UNION ALL
SELECT number+1 FROM Numbers WHERE number < 10)
SELECT * FROM Numbers

答案 2 :(得分:2)

首先创建一个数字表0 - 9

create table dbo.Digits (digit tinyint not null Primary Key) 
insert into dbo.Digits values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9)

然后,您可以生成以下交叉连接,从1到100进行计数:

select
D2.digit * 10 + 
D1.digit + 1 as n
from dbo.Digits D1,
dbo.Digits D2
order by n

要从1到1000计数,您只需添加一个额外的交叉连接:

select
D3.digit * 100 +
D2.digit * 10 + 
D1.digit + 1 as n
from dbo.Digits D1,
dbo.Digits D2,
dbo.Digits D3
order by n

从1到x(其中x <= 1000)::

进行计数
select top x
D3.digit * 100 +
D2.digit * 10 + 
D1.digit + 1 as n
from dbo.Digits D1,
dbo.Digits D2,
dbo.Digits D3
order by n

答案 3 :(得分:2)

绝对不是最优雅,但可能是更大序列的最快方式:

WITH
 E1(N) AS (SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
           SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
           SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
           SELECT 1),                 --10E1  or 10 rows
 E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E2  or 100 rows
 E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E3  or 10000 rows
 E8(N) AS (SELECT 1 FROM E4 a, E4 b)  --10E4  or 100000000 rows
SELECT TOP (@DesiredRowCount) N = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E8
;

没有临时表,没有表格读取,您可以自己定义最大值。

您可以从here

复制粘贴即用型功能

答案 4 :(得分:1)

根据需要修改Top值:

SELECT TOP 30 ROW_NUMBER() OVER (ORDER BY [object_id]) 
FROM sys.all_objects

e.g。下拉列表显示NULL范围,1 - 30表示教育年份列表。

<tr>
<td>Education</td>
<td>
<asp:DropDownList ID="EducationDropDownList" runat="server" DataSourceID="sd6"
 DataValueField="Education" DataTextField="Education" 
 SelectedValue='<%# Bind("Education") %>' CssClass="metro" />
<asp:SqlDataSource ID="sd6" runat="server" 
 ConnectionString="<%$ ConnectionStrings:cnYours %>" 
 SelectCommand="SELECT NULL AS Education UNION ALL SELECT TOP 30 ROW_NUMBER() OVER (ORDER BY [object_id]) FROM sys.all_objects" 
 SelectCommandType="Text" />
</td>
</tr>

答案 5 :(得分:1)

如果您只希望输出包含一个正在运行的编号作为附加列,则以下内容也可以使用:

select row_number() over (order by (Select 1)) AS RowNum, * from Table_1 where Column_3 = 372 and Column_6 = 2017;