Альтернатива LAG() в SQL Server

#sql #sql-server #common-table-expression #calculation #cumulative-sum

#sql #sql-сервер #common-table-expression #вычисление #кумулятивная сумма

Вопрос:

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: новое в программировании SQL Server

В настоящее время я работаю над вычислением в SQL, которое я не могу понять.

По сути, это вычисление, при котором у вас есть начальный баланс, некоторые вычисления, которые зависят от начального баланса и конечного баланса. Конечный результат таблицы должен быть следующим:

 | Employee  | ROWN |Balance_year1 | O_balance | calc   | C_balance |
--------------------------------------------------------------------
| Emp1      |  1   | 1000         | 1000      | 20     | 1020      |
| Emp1      |  2   | 1000         | 1020      | 20.4   | 1040.4    | 
| Emp1      |  3   | 1000         | 1040.4    | 20.808 | 1061.208  | 
| Emp2      |  1   | 2000         | 2000      | 40     | 2040      |
| Emp2      |  2   | 2000         | 2040      | 40,8   | 2080,8    |
| Emp2      |  3   | 2000         | 2080,8    | 41,616 | 2122,416  |
  

До сих пор я писал код следующим образом:

 WITH table1 AS (
    SELECT
       *
     , [O_balance] = LAG([C_balance], 1, [Balance_year1]) OVER (PARTITION BY [Employee] ORDER BY [ROWN] ASC)
    FROM dataset
),
table2 AS (
    SELECT 
       *
     , [calc]      = --Some calculations that depends on the [C_balance] from the row before
    FROM table1
)
SELECT 
    *
  , [O_balance]
  , [calc]
  , [C_balance] = [O_balance]   [calc]  
FROM table2
  

Мои проблемы с таблицей:

  1. [C_balance] Не вычисляется при использовании в первом CTE, поэтому он не может быть запущен. (Недопустимое имя столбца [C_balance] )
  2. Вычисляется [C_balance] неправильно, когда оно используется в [calc] .

Я полагаю, что вы можете либо вычислять таблицу строка за строкой, либо сохранять [C_balance] в переменной и обновлять ее на протяжении всего выполнения, но idk?

Я надеюсь, что один из вас, ребята, сможет мне помочь — борьба реальна 🙂 Спасибо!

Комментарии:

1. Есть ли столбец [C_balance] в dataset ?

2. Нет, все столбцы, которые я создал после *, являются добавленными столбцами для вычисления

3. Тогда от чего вы ожидаете LAG([C_balance], 1, [Balance_year1]) ?

4. У вас есть альтернатива? Я пробовал много разных вещей, но я подумал, что этот неудачный пример будет лучшим, чтобы показать вам, чтобы дать вам представление о проблеме 🙂 Я могу сообщить вам тот факт, что существуют языки, на которых вы можете просмотреть одну строку в качестве функции просмотра, которую я Qlik

Ответ №1:

Вы можете делать все, что хотите, с помощью рекурсивного CTE:

 with cte as (
      select employee, rown, balance, balance as o_balance, balance * 1.02 as c_balance
      from dataset
      where rown = 1
      union all
      select d.employee, d.rown, d.balance, cte.c_balance, cte.c_balance * 1.02
      from cte join
           dataset d
           on cte.employee = d.employee and d.rown = cte.rown   1
    )
select *
from cte;
  

Я немного размышляю о том, каковы ваши вычисления, но это работает для предоставленных вами данных.

Комментарии:

1. Спасибо за вашу помощь — это помогло решить проблему, которую я опубликовал. Я не очень хорошо объяснил quiet с первой попытки (sry —> думаю, я новичок). Можете ли вы проверить мои изменения в таблице? Спасибо!

2. @xxxKryptoPiratenxxx … Обычно вам следует задать новый вопрос. В этом случае я подумал, что вы на самом деле намеревались сделать это с помощью employee, и модификация довольно тривиальна, поэтому я обновил ответ.

Ответ №2:

Для меня это выглядит как проблема с текущей суммой (и вопрос помечен как таковой, поэтому я собираюсь пойти с ним). Во-первых, код:

 with d as (
    select * from (values
        ('Emp1',  1   , 1000         , 1000      , 20     , 1020      ),
        ('Emp1',  2   , 1000         , 1020      , 20.4   , 1040.4    ), 
        ('Emp1',  3   , 1000         , 1040.4    , 20.808 , 1061.208  ), 
        ('Emp2',  1   , 2000         , 2000      , 40     , 2040      ),
        ('Emp2',  2   , 2000         , 2040      , 40.8   , 2080.8    ),
        ('Emp2',  3   , 2000         , 2080.8    , 41.616 , 2122.416  )
    ) as x(Employee  , ROWN ,Balance_year1 , O_balance , calc   , C_balance)
), c as (
    select *, balance_year1   sum(calc) over (partition by employee order by rown) as myCalc
    from d
)
select *, C_balance - myCalc
from c
  

Я использую здесь обычные табличные выражения только для простоты использования — первое, чтобы получить ваши данные в удобном формате, второе, чтобы показать промежуточный шаг. Последний запрос показывает, что мои вычисления и ваши дают один и тот же ответ. «Волшебство» — это sum(calc) over (partition by employee order by rown) бит. В достаточно современных версиях SQL (введенных в 2012 году iirc, но, возможно, даже раньше) вы можете сделать это, чтобы получить текущую сумму.