我有一张这样的桌子
ItemsWithQuantity
=================
ID Quantity
---------------
x 4
y 7
我想建立一个视图或查询,把它变成这个
ID
x
x
x
x
y
y
y
y
y
y
y
基本上不计算它们,并为每个数量获得一个唯一的行。
在 MS SQL 2005 或 2008 中动态执行此操作的最佳方法是什么
我有一张这样的桌子
ItemsWithQuantity
=================
ID Quantity
---------------
x 4
y 7
我想建立一个视图或查询,把它变成这个
ID
x
x
x
x
y
y
y
y
y
y
y
基本上不计算它们,并为每个数量获得一个唯一的行。
在 MS SQL 2005 或 2008 中动态执行此操作的最佳方法是什么
最简单的方法:
SELECT iq.ID FROM ItemsWithQuantity iq
INNER JOIN master..spt_values n ON iq.Quantity > n.number AND n.type = 'p'
这是将master..spt_values
系统表用于数字,这是一个非常安全但仍未记录的功能。如果您不确定是否使用它,您可以创建自己的 Numbers 表来仅列出数字,或者动态创建 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
首先创建一个数字表 ( (ID INT NOT NULL PRIMARY KEY)
),其中包含从 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
CROSS APPLY
读作“对于每个外行,加入以下行”。在我们的例子中,我们将Quantity
内部行连接到每个外部行。
这是一种使用循环的方法。不需要外部表或交叉表引用。
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
更新
使用临时表,您可以从一个查询中选择全部。