Условно выбирайте строку каждый месяц - SQL Server - PullRequest
0 голосов
/ 08 октября 2019

У меня есть таблица, tblTRX, которая выглядит следующим образом:

| Person | Counter | Transaction |   Tdate   | Ttype | Inventory |
|:------:|:-------:|:-----------:|:---------:|:-----:|:---------:|
|  Bill  |    D    |      -4     |  1/1/2019 |  SALE |     99    |
|  Bill  |    DA   |      -3     | 1/15/2019 |  SALE |     96    |
|  Susan |    DA   |      -3     | 1/21/2019 |  SALE |     93    |
|  Bill  |    AA   |      -2     | 2/22/2019 |  SALE |     91    |
| George |    AC   |      -2     |  3/4/2019 |  EMP  |     89    |
|  Susan |    AC   |      -2     |  3/5/2019 |  SALE |     87    |
|  Susan |    AA   |      -1     |  3/6/2019 |  SALE |     86    |
|  Susan |    D    |      -2     |  3/7/2019 |  SALE |     84    |
|  Susan |    AA   |      -4     |  3/8/2019 |  SALE |     80    |
|  Susan |    AB   |      -4     |  3/9/2019 |  SALE |     76    |
|  Susan |    AC   |      -4     | 3/10/2019 |  EMP  |     72    |
|  Susan |    D    |      -4     |  4/6/2019 |  SALE |     68    |
|  Susan |    D    |      -3     |  5/1/2019 |  SALE |     65    |
|  Susan |    AB   |      -3     |  5/9/2019 |  SALE |     62    |
| George |    DA   |      -1     | 5/22/2019 |  SALE |     61    |
| George |    AA   |      -4     | 5/23/2019 |  SALE |     57    |
| George |    DA   |      -3     | 6/11/2019 |  EMP  |     54    |
|  Bill  |    AA   |      -3     | 6/19/2019 |  EMP  |     51    |
| George |    AC   |      -4     | 6/20/2019 |  SALE |     47    |
|  Susan |    AB   |      -2     | 6/21/2019 |  SALE |     45    |
|  Bill  |    D    |      -4     |  7/2/2019 |  SALE |     41    |
|  Bill  |    DA   |      -4     |  7/3/2019 |  SALE |     37    |
| George |    D    |      -4     |  7/4/2019 |  EMP  |     33    |
|  Bill  |    AB   |      -1     |  8/2/2019 |  SALE |     32    |
|  Bill  |    AC   |      -2     | 9/20/2019 |  SALE |     30    |
|  Susan |    D    |      -3     | 9/23/2019 |  EMP  |     27    |

Я хотел бы, чтобы каждый месяц добавлялся коэффициент истощения для каждого сотрудника. Они хранятся в таблице tblATTR, которая выглядит следующим образом:

|  Employee  |  AttrRate |
|:----------:|:---------:|
| Bill       |  -5       |
| George     |  2        |
|  Susan     | -10       |

Раз в месяц мне требуется коэффициент истощения для каждого сотрудника, добавляемый как транзакция в tblTRX.

Результат цели будет выглядеть следующим образом:

| Person | Counter | Transaction |   Tdate   | Ttype | Inventory |
|:------:|:-------:|:-----------:|:---------:|:-----:|:---------:|
|  Bill  |    D    |      -4     |  1/1/2019 |  SALE |     99    |
|  Bill  |   NULL  |      -5     |  1/1/2019 |  ATTR |     94    |
| George |   NULL  |      2      |  1/1/2019 |  ATTR |     96    |
|  Susan |   NULL  |     -10     |  1/1/2019 |  ATTR |     86    |
| George |    DA   |      -3     | 1/15/2019 |  SALE |     83    |
|  Susan |    DA   |      -3     | 1/21/2019 |  SALE |     80    |
|  Bill  |   NULL  |      -5     |  2/1/2019 |  ATTR |     75    |
| George |   NULL  |      2      |  2/1/2019 |  ATTR |     77    |
|  Susan |   NULL  |     -10     |  2/1/2019 |  ATTR |     67    |
|  Bill  |    AA   |      -2     | 2/22/2019 |  SALE |     78    |
|  Bill  |   NULL  |      -5     |  3/1/2019 |  ATTR |     73    |
| George |   NULL  |      2      |  3/1/2019 |  ATTR |     75    |
|  Susan |   NULL  |     -10     |  3/1/2019 |  ATTR |     65    |
| George |    AC   |      -2     |  3/4/2019 |  EMP  |     63    |
|  Susan |    AC   |      -2     |  3/5/2019 |  SALE |     61    |
|  Susan |    AA   |      -1     |  3/6/2019 |  SALE |     60    |
|  Susan |    D    |      -2     |  3/7/2019 |  SALE |     58    |
|  Susan |    AA   |      -4     |  3/8/2019 |  SALE |     54    |
|  Susan |    AB   |      -4     |  3/9/2019 |  SALE |     50    |
|  Susan |    AC   |      -4     | 3/10/2019 |  EMP  |     46    |
|  etc…  |         |             |           |       |           |

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

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

for each MONTH in tblTRX:
    on month/01/year, insert attrition rates for each employee
    recalculate inventory

Я знаю, что могу использовать функцию SUM с вызовом ROW_NUMBER(), чтобы продолжить суммирование инвентаря из текущей транзакции и инвентаря из строки перед, так что это не так важно, как периодическая вставка строки в поток данных таблицы.

Ответы [ 2 ]

0 голосов
/ 08 октября 2019

Вы можете попробовать это

INSERT INTO tblTRX (Person, [Transaction], Tdate, Ttype)
SELECT B.Employee, B.AttrRate, CONCAT(M,'/1/',Y) , 'ATTR' 
FROM
    (SELECT DISTINCT YEAR(Tdate) Y, MONTH(TDate) M  FROM tblTRX) AS A 
    CROSS JOIN tblATTR B
WHERE 
    NOT EXISTS( SELECT * FROM tblTRX X WHERE X.Person = B.Employee AND X.Ttype = 'ATTR' AND X.Tdate = CONCAT(M,'/1/',Y) );

WITH CTE AS
(SELECT 
        *, FIRST_VALUE(Inventory) OVER(ORDER BY TDate, ID) 
          - FIRST_VALUE([Transaction]) OVER(ORDER BY TDate, ID) 
          + SUM([Transaction]) OVER(ORDER BY TDate, ID) as NewInventory
 FROM tblTRX )
UPDATE CTE set Inventory = NewInventory
0 голосов
/ 08 октября 2019

Вы можете получить идею из приведенного ниже кода, не можете быть протестированы и нуждаются в корректировке наверняка. Запрос получает записи attr, лучше сохранить некоторые результаты во временных таблицах.

    -- Get the last Attr month for each user, 
    ;WITH cteA
    AS
    (
      SELECT Person,MAX(Tdate) AS LastAttrDate
      FROM tblTRX
      WHERE tType=N'ATTR'
      GROUP BY Person
    ),
   -- first and last transaction for each user
    cteT
    AS
    (
      SELECT Person,CONVERT(DATE,LEFT(CONVERT(nvarchar(30),MAX(Tdate),120),7)+N'-01'),120) AS LastTrxDate,
        CONVERT(DATE,LEFT(CONVERT(nvarchar(30),MIN(Tdate),120),7)+N'-01'),120) AS FirstTrxDate
      FROM tblTRX
      WHERE tType<>N'ATTR'
      GROUP BY Person
    ),
    -- calculate the month range to insert
    cteM
    AS
    (
      SELECT T.Person, CASE WHEN A.LastAttrDate IS NULL TEHN T.FirstTrxDate ELSE DATEADD(MONTH,1,A.LastAttrDate) AS StartMonth,
        T.LastTrxDate AS EndMonth
      FROM cteA A
      RIGHT JOIN cteT T
      ON A.Person=T.Person
    ),
    -- recursively generates the months
    cteAM
    (
      SELECT Person,StartMonth,DATEADD(Month,1,StartMonth) AS EndMonth, EndMonth AS LastTrxMonth
      FROM cteM
      WHERE EndMonth>=StartMonth
      UNION ALL
      SELECT Person,DATEADD(Month,1,StartMonth),DATEADD(Month,1,EndMonth),LastTrxMonth
      FROM cteAM
      WHERE LastTrxMonth>=StartMonth
    ),
    -- the inventory to do the cal
    cteIn
    (
      SELECT A.Person,MIN(T.Tdate) AS InvDate
      FROM tbTRX T
      INNER JOIN cteAM A
      ON T.Person=A.Person
      AND T.TDate >=A.StartMonth
      AND T.TDate<A.EndMonth
      GROUP BY A.Person
    )

    SELECT A.Person,NULL AS Counter, A.Attr AS Transaction, M.StartMonth AS TDate, 'ATTR' AS Ttype, T.Inventory + A.Attr AS Inventory
    FROM tbTRX T
    INNER JOIN cteIn I ON T.Person=I.Person AND T.TDate=I.InvDate
    INNER JOIN tblATTR A ON A.Person=I.Person
    INNER JOIN cteAM M ON M.Person=A.Person
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...