我有一个包含美元金额字段的会计表。 我想创建一个视图,该视图将返回该金额的每便士一行以及表中的其他一些字段。
所以作为一个非常简单的例子,假设我有这样的行:
PK Amount Date
---------------------------
123 4.80 1/1/2012
查询/视图应返回 480 行(每分钱一行),如下所示:
PK Date
-----------------
123 1/1/2012
实现此目的的最高性能方法是什么? 我有一个使用表值函数和临时表的解决方案,但在我的脑海中,我一直认为必须有一种方法可以用传统视图来实现这一点。 可能是一个创造性的交叉联接或将返回此结果的东西,而不必以临时表和 tbf 等形式声明太多资源。 有什么想法吗?
在数字表的帮助下,您可以这样做:
select PK, [Date]
from YourTable as T
inner join number as N
on N.n between 1 and T.Amount * 100
如果你周围没有,你想测试这个,你可以使用master..spt_values。
declare @T table
(
PK int,
Amount money,
[Date] date
)
insert into @T values
(123, 4.80, '20120101')
;with number(n) as
(
select number
from master..spt_values
where type = 'P'
)
select PK, [Date]
from @T as T
inner join number as N
on N.n between 1 and T.Amount * 100
更新:
摘自杰夫·莫登的一篇文章。
"数字"或"计数"表:它是什么以及它如何替换循环。
计数表只不过是具有单列 索引非常好的序列号从 0 或 1 开始(我的从 1)并上升到某个数字。计数表中的最大数字 不应该只是一些随意的选择。它应该基于什么 你认为你会用它来。我将 VARCHAR(8000) 与我的分开,所以它 必须至少为 8000 个数字。因为我偶尔需要生成 30 年的日期,我的大部分生产计数表保持在 11,000 或更多,即超过 365.25 天乘以 30 年。
CTE,如下所示:
WITH duplicationCTE AS
(
SELECT PK, Date, Amount, 1 AS Count
FROM myTable
UNION ALL
SELECT myTable.PK, myTable.Date, myTable.Amount, Count+1
FROM myTable
JOIN duplicationCTE ON myTable.PK = duplicationCTE.PK
WHERE Count+1 <= myTable.Amount*100
)
SELECT PK, Date
FROM duplicationCTE
OPTION (MAXRECURSION 0);
这是 SqlFiddle
并且,请注意 0。这意味着这可以无限运行(顺便说一句,危险)否则,32676 是您可以设置的最大递归数(默认值为 100)。但是,如果您正在运行超过 32676 个循环,那么您可能需要重新考虑您的逻辑:)