在SQL Server中,有什么方法可以像在其他任何编程语言中操作数组那样处理数据吗?
我有一个SQL查询返回3列,即“ dt_ref”(日期),“ vlr_venda”(浮动)和“ qt_parcelas”(int)
基本上,我需要执行以下操作:
- When field "qt_parcelas" is higher than 1, I need to do a "loop" with this row and generate 3 rows.
因此,我需要将字段“ vlr_venda”除以字段“ qt_parcelas”,并使用字段“ dt_ref”作为日期字段中日期的开始和增量月份的参考,以获取“ qt_parcelas”的值
例如,如果我的查询返回以下结构:
| dt_ref | vlr_venda | qt_parcelas |
-------------------------------------
|20180901 | 3000 | 3 |
我需要做些事情来返回这个:
| dt_ref | vlr_venda |
----------------------
|20180901 | 1000 |
|20181001 | 1000 |
|20181101 | 1000 |
是否可以在SQL Server中完成? 我已经搜索过类似的内容,但没有发现任何有用的内容... 有什么想法吗?
答案 0 :(得分:2)
您可以使用递归CTE:Sql Fiddle
with cte as (
select dt_ref, vlr_venda / qt_parcelas as new_val, qt_parcelas, 1 as num
from t
union all
select dateadd(month, 1, dt_ref), new_val, qt_parcelas, num + 1
from cte
where num < qt_parcelas
)
select dt_ref, new_val
from cte;
按照书面规定,这最多可以使用100个月。您需要添加OPTION (MAXRECURSION 0)
更长的时间。
答案 1 :(得分:0)
可以使用计数表代替使用rCTE。如果您的数字比3大得多,这可能会很有效:
WITH N AS(
SELECT n
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(n)),
Tally AS (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) I
FROM N N1 --10 rows
CROSS JOIN N N2 --100 rows
--CROSS JOIN N N3 --Keep adding more CROSS JOINs to create more rows
),
VTE AS (
SELECT CONVERT(date,V.dt_ref) AS dt_ref,
V.vlr_venda,
V.qt_parcelas
FROM (VALUES('20180901',3000,3),
('20181001',12000,6)) V(dt_ref,vlr_venda ,qt_parcelas))
SELECT DATEADD(MONTH,T.I,V.dt_ref),
CONVERT(decimal(10,4),V.vlr_venda / (V.qt_parcelas * 1.0)) --incase you need decimal points
FROM VTE V
JOIN Tally T ON V.qt_parcelas >= T.I;
答案 2 :(得分:0)
我开发了一个软件来生成票证,而且我的经历与您相似。我尝试了CURSORS和递归CTE,在为客户创建票证时它们都花费了大约50分钟的时间
我使用此功能来复制客户并生成票证
/****** Object: UserDefinedFunction [dbo].[NumbersTable] Script Date: 28/09/2018 10:51:25 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[NumbersTable] (
@fromNumber int,
@toNumber int,
@byStep int
)
RETURNS @NumbersTable TABLE (i int)
AS
BEGIN
WITH CTE_NumbersTable AS (
SELECT @fromNumber AS i
UNION ALL
SELECT i + @byStep
FROM CTE_NumbersTable
WHERE
(i + @byStep) <= @toNumber
)
INSERT INTO @NumbersTable
SELECT i FROM CTE_NumbersTable OPTION (MAXRECURSION 0)
RETURN;
END
GO
然后您可以使用
CROSS APPLY dbo.NumbersTable(1,qt_parcelas ,1);
生成行
以这种方式相信我,效率更高,并且在处理大量数据(大约8到1千万行)时,大约需要2分钟而不是40分钟。