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的数字。按照我的解决方案,这是不必要的。