SQL Server-处理数据并返回新结果

时间:2018-09-28 14:38:38

标签: sql sql-server tsql

在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中完成? 我已经搜索过类似的内容,但没有发现任何有用的内容... 有什么想法吗?

3 个答案:

答案 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分钟。