SQL Server - манипулируйте данными и возвращайте новые результаты - PullRequest
0 голосов
/ 28 сентября 2018

Есть ли способ сделать что-то в 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?Я искал что-то подобное, но не нашел ничего полезного ... Есть идеи?

Ответы [ 3 ]

0 голосов
/ 28 сентября 2018

Вместо использования 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;
0 голосов
/ 28 сентября 2018

Я разработал программное обеспечение для генерации билетов, и у меня был похожий опыт, чем у вас.Я пробовал 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 до 10 миллионов строк) требуется что-то вроде 2минут вместо 40

0 голосов
/ 28 сентября 2018

Вы можете использовать рекурсивный 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) для более длительных периодов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...