Sql 获取一个带有数量字段或项目计数的表,并动态地为每个字段创建唯一的行

Sql 获取一个带有数量字段或项目计数的表,并动态地为每个字段创建唯一的行,sql,sql-server,sql-server-2008,sql-server-2005,Sql,Sql Server,Sql Server 2008,Sql Server 2005,我有一张这样的桌子 ItemsWithQuantity ================= ID Quantity --------------- x 4 y 7 我想构建一个视图或查询,将其转换为 ID x x x x y y y y y y y 基本上不计算它们,并为每个数量获得唯一的行 动态执行此操作的最佳方法是什么,在MS SQL 2005或2008中创建一个数字表first ID INT NOT NULL主键,数字范围为1到1m 然后,查询变

我有一张这样的桌子

 ItemsWithQuantity
 =================
 ID     Quantity
 ---------------
 x      4
 y      7
我想构建一个视图或查询,将其转换为

ID
x
x
x
x
y
y
y
y
y
y
y
基本上不计算它们,并为每个数量获得唯一的行


动态执行此操作的最佳方法是什么,在MS SQL 2005或2008中创建一个数字表first ID INT NOT NULL主键,数字范围为1到1m

然后,查询变得更简单:

SELECT tab.ID
FROM ItemsWithQuantity tab
CROSS APPLY (
 SELECT ID FROM Numbers WHERE ID BETWEEN 1 AND Quantity
) x
ORDER BY tab.ID
交叉应用读起来就像对于每个外部行,连接以下行。在我们的例子中,我们将数量内部行连接到每个外部行。

最简单的方法:

SELECT iq.ID FROM ItemsWithQuantity iq
INNER JOIN master..spt_values n ON iq.Quantity > n.number AND n.type = 'p'
这是使用master..spt_values系统表来表示数字,这是一个非常安全但尚未记录的特性。如果您不确定是否要使用它,您可以创建自己的数字表,该表只列出数字,或者动态创建CTE:

WITH CTE_Numbers AS
(
    SELECT MAX(Quantity) AS Number FROM dbo.ItemsWithQuantity
    UNION ALL
    SELECT number - 1 FROM CTE_Numbers
    WHERE number >=1
)
SELECT iq.ID FROM ItemsWithQuantity iq
INNER JOIN CTE_Numbers n ON iq.Quantity > n.number
ORDER BY ID

这里有一种使用循环的方法。不需要外部表或交叉表引用

DECLARE @i INT = 1
DECLARE @counter INT
CREATE TABLE ##tempTable(
    ID INT
)
WHILE @i<=(
SELECT COUNT(*) FROM ItemsWithQuantity)
BEGIN
    SET @counter=(SELECT QuantityFROM(
    SELECT ROW_NUMBER() OVER (ORDER BY ID DESC) RowNumber, * FROM ItemsWithQuantity) a
    WHERE RowNumber=@i)
    WHILE @counter>=0 BEGIN
        INSERT INTO ##tempTable (ID) SELECT ID FROM(
            SELECT ROW_NUMBER() OVER (ORDER BY ID DESC) RowNumber, * FROM ItemsWithQuantity) a
            WHERE RowNumber=@i)
        SET @counter=@counter-1
    END
    SET @i=@i+1
END
SELECT * FROM ##tempTable
更新


使用临时表,您可以从一个查询中选择所有查询。

您是否有表序列?不是downvoter,但与其他两个答案相比,这似乎非常不合法且效率低下。我很想看看这三种方案的执行计划和性能有什么不同。@littlebbytables这两种解决方案都需要创建一个包含大量数字的表,即从1到1m的数字。按照我的解决方案,这是不必要的。