SQL Server-操作数据并返回新结果
在SQL Server中是否有任何方法可以像在任何其他编程语言中操纵数组一样操纵数据 我有一个SQL查询,返回3列:dt_ref date、vlr_venda float和qt_parcelas int 基本上,我需要这样做:SQL Server-操作数据并返回新结果,sql,sql-server,tsql,Sql,Sql Server,Tsql,在SQL Server中是否有任何方法可以像在任何其他编程语言中操纵数组一样操纵数据 我有一个SQL查询,返回3列:dt_ref date、vlr_venda float和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
- 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中执行此操作?
我已经搜索过类似的东西,但没有找到任何有用的。。。
有什么想法吗?您可以使用递归CTE:
如前所述,这将持续100个月。您需要在更长时间内添加选项MAXRECURSION 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;
我开发了一个生成门票的软件,我的经历和你相似。我尝试过游标和递归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
生成您的行
相信我,这种方式效率更高,在处理大量数据(如800万到1000万行)时,需要2分钟而不是40分钟,这是您可能不希望在纯SQL中执行的业务逻辑。这不仅仅是因为需要一个计数表或递归有点不方便,因为您可以使用它,而是因为有更好的语言和更好的编码环境来表达和记录它们,特别是当需求随着时间的推移变得更加复杂时。如果这是一次性的转换,那也没关系;如果您必须连续执行此操作,则不需要太多。作为内联表值函数,这可能会更好。您基本上就在那里,所以不确定为什么选择多行选项:谢谢正是我需要的!这把小提琴棒极了!
/****** 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);