【问题标题】:SQL select numbers - dynamically with incrementing value in each rowSQL 选择数字 - 动态地在每行中递增值
【发布时间】:2017-11-27 17:54:16
【问题描述】:

有没有办法编写一个动态的 sql 选择语句(不查询表/列),它会返回类似这样的内容

id
1
2
3
4
5
... 
etc. 

我需要编写几个从 1 到 X 的通用查询
(X 将由不同的查询预先确定)。

假设 X 为 5,数据将返回 5 行,其中 1 2 3 4 5
如果 X 为 27,则数据将返回 1 2 3 ... 27 等等。

关于附加评论,这是在第三方 sybase 软件中使用的,我仅限于查询的复杂性,它似乎创建和删除表似乎不起作用

【问题讨论】:

  • 在你提到的third party sybase softwarecomplexity of temp tables的cmets中;您可能希望使用有关您的环境的其他详细信息来更新您的问题(例如,您是否正在编写将在远程 Sybase ASE 数据库上运行的 SQL Server T-SQL 代码等),以包括各种产品名称和版本;我们拥有的细节越多越好……否则我们可能会浪费时间发布在您的环境中不可接受/不可行的答案
  • 我还建议您提供一个更详细的示例,说明您计划如何使用这些数字;按照目前的措辞,我不知道你是否想将这些数字用于插入、删除、更新、选择……如果你想将它们用于加入/SARG 目的……如果是select,为什么你可以不要做类似select * from some_table where id between 1 and X
  • 这个问题向我表明,SArg 不会成为 Op 认可的术语。
  • 另一个问题...您期望 X 的最大值是多少?

标签: sql-server select auto-increment numeric


【解决方案1】:

【讨论】:

  • 我无法使用如此复杂的东西,数据将发送到第三方 sybse 软件,我可以处理基本的简单查询,这让我很难过(虽然谢谢你的提示,我学到了一些新东西)
  • 计数表并不复杂。这是迄今为止最干净和最简单的解决方案。创建一个从 0 到 的数字表,然后使用连接。例如 0..86399 为一天中的每一秒提供一个条目。或 0..1023 提供了一个表,您可以反复连接自己以获得有用且任意大范围的值...SELECT * FROM dbo.numbers WHERE id BETWEEN 1 AND 27 就像您将得到的一样简单...
【解决方案2】:

你可以尝试这样的递归 CTE

declare @mx integer=4

;with test as (
select 1 as id
union all
select id+1
from test
where id<@mx
)
select * from test

【讨论】:

  • 可能想要包含MAXRECURSION(0) 以防止遇到超过 100 的奇怪行为。然后解释当您达到 32k 及以上时存在的成本/问题...
  • 这里要小心...用于计数的 cte 基本上是一个循环。 sqlservercentral.com/articles/T-SQL/74118
【解决方案3】:

27 选择:

DECLARE @Count int = 1
DECLARE @MaxCount int = 27 -- Whatever your incoming max is

WHILE @Count <= @MaxCount
BEGIN
SELECT @Count

SELECT @Count = @Count + 1
END

单选:

CREATE TABLE #TEMPNUMS (AUTONUM INT IDENTITY (1,1), GHOSTVAL VARCHAR(1))


DECLARE @Count int = 1
DECLARE @MaxCount int = 27 -- Whatever your incoming max is

WHILE @Count <= @MaxCount
BEGIN
INSERT INTO #TEMPNUMS (GHOSTVAL)
SELECT ''

SELECT @Count = @Count + 1
END

SELECT AUTONUM FROM #TEMPNUMS

DROP TABLE #TEMPNUMS

【讨论】:

  • 我不知道您是想要 27 次单选还是一次选择 27 行。两个答案都包括在内。
  • 1 选择 27 行。
  • 一键更新答案。
  • 这将在第三方应用程序中,我必须确认是否支持临时表的复杂性。
  • 即使您发现新的信息使它们无效,您仍然应该对回答您的原始问题的答案投赞成票 :)
【解决方案4】:

你试过这样使用 CTE 吗?

WITH OrderedRows (ROWN)
AS (
    SELECT 1 AS ROWN

    UNION ALL

    SELECT r.ROWN + 1 AS ROWN
    FROM OrderedRows r
    WHERE r.ROWN < 100
    )
SELECT *
FROM OrderedRows

【讨论】:

  • 可能想要包含MAXRECURSION(0) 以防止遇到超过 100 的奇怪行为。然后解释当您达到 32k 及以上时存在的成本/问题...
  • 另外,最好从两个值(0 和 1)开始,然后开始将表加入到自身 (每个级别的递归使您正在使用的范围加倍,提供了很多更高的范围和更好的缩放).
  • 这里要小心...用于计数的 cte 基本上是一个循环。 sqlservercentral.com/articles/T-SQL/74118
【解决方案5】:

假设您的最大数量永远不会大于 9999。如果是,那么您将需要重组查询以添加另一个层。

DECLARE @MaxCount int = 27 -- Whatever your incoming max is

SELECT ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n
FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) ones(n),
     (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) tens(n),
     (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) hundreds(n),
     (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) thousands(n)
     where ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n between 1 and @MaxCount
ORDER BY 1

查看另一个类似问题的答案:How to generate a range of numbers between two numbers?

【讨论】:

  • 只是为了避免重复自己,你可以有类似WITH ten AS SELECT * FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) ones(n)) SELECT blah FROM ten ones CROSS JOIN ten tens CROSS JOIN ten hundreds blahblahblah...
猜你喜欢
  • 2010-10-08
  • 1970-01-01
  • 1970-01-01
  • 2018-01-01
  • 1970-01-01
  • 2021-10-08
  • 1970-01-01
  • 2018-11-29
  • 2018-02-23
相关资源
最近更新 更多