Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server-操作数据并返回新结果_Sql_Sql Server_Tsql - Fatal编程技术网

SQL Server-操作数据并返回新结果

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

在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,并使用字段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);