подведение итогов с использованием MySQL - PullRequest
0 голосов
/ 03 мая 2018

(см. Запрос и обновление результатов ниже, работающей системы, если я жестко закодировал портфель) Я пытаюсь создать промежуточную сумму платежного баланса одним из двух способов, используя mysql (используя sub select и используя переменные), однако оба метода не дают правильных результатов. Первый метод наиболее близок только к ошибкам, когда даты совпадают, хотя этот метод менее эффективен, чем использование переменных.

В отчете показаны выплаты дивидендов по портфелю (ам) акций в последовательности даты платежа (pdate), сгруппированной по дате платежа, портфелю и доле (код)

SELECT
  d.code                                      AS code,
  p.name                                      AS portfolio,
  d.pdate                                     AS pdate,
  d.dividend                                  AS dividend,
  CEILING(SUM(t.quantity))                    AS quantity,
  CEILING(SUM(t.quantity) * d.dividend / 100) AS payment,

  (
    SELECT CEILING(SUM(din.dividend * tin.quantity) / 100)
    FROM
      transaction tin
      INNER JOIN member min ON (tin.member_id = min.id)
      INNER JOIN dividend din ON (tin.code = din.code)
      INNER JOIN portfolio pin ON (tin.portfolio_id = pin.id)
    WHERE
      (min.id >= '01' AND min.id <= '02')
      AND
      din.pdate <= d.pdate
      AND
      din.pdate >= NOW()
      AND
      pin.name <> 'FDR_JNT'
  ) AS balance
FROM
  transaction t
  INNER JOIN member m ON (m.id = t.member_id)
  INNER JOIN portfolio p ON (p.id = t.portfolio_id)
  INNER JOIN account a ON (a.id = p.account_id)
  INNER JOIN dividend d ON (d.code = t.code)
WHERE
  (m.id >= '01' AND m.id <= '02')
  AND
  d.exchange = t.exchange
  AND
  d.pdate >= NOW()
GROUP BY pdate, portfolio, code

Результаты показаны ниже, баланс по RHS

+----------+---------------+--------------+---------------+--------------+-------------+----------+
| code     | portfolio     | pdate        | dividend      | quantity     | payment     | balance  |
+----------+---------------+--------------+---------------+--------------+-------------+----------+
| BLND     | AJB_SIPP_CO   | 2018-05-05   | 7.52          | 1643         | 124         | 124      |
| AV.      | AJB_SIPP_CO   | 2018-05-17   | 15.88         | 2135         | 340         | 831      |
| AV.      | SFT_DEA_CO    | 2018-05-17   | 15.88         | 2318         | 369         | 831      |
| DLG      | AJB_SIPP_CO   | 2018-05-18   | 9.7           | 2732         | 266         | 1367     |
| DLG      | SFT_DEA_CO    | 2018-05-18   | 9.7           | 2789         | 271         | 1367     |
| SLA      | AJB_SIPP_CO   | 2018-05-23   | 13.35         | 2820         | 377         | 2177     |
| SLA      | SFT_DEA_CO    | 2018-05-23   | 13.35         | 3247         | 434         | 2177     |
| PHP      | AJB_SIPP_CO   | 2018-05-27   | 1.31          | 6947         | 92          | 2268     |
| LLOY     | AJB_SIPP_CO   | 2018-05-29   | 2.05          | 15519        | 319         | 3569     |
| LLOY     | SFT_DEA_CL    | 2018-05-29   | 2.05          | 40011        | 821         | 3569     |
| LLOY     | SFT_ISA_CO    | 2018-05-29   | 2.05          | 7973         | 164         | 3569     |
| FCPT     | AJB_SIPP_CL   | 2018-05-31   | 0.5           | 223          | 2           | 3809     |
+----------+---------------+--------------+---------------+--------------+-------------+----------+

Я также пытался использовать второй метод с использованием переменных следующим образом

SELECT
  d.code                                          AS code,
  p.name                                          AS portfolio,
  d.pdate                                         AS pdate,
  d.dividend                                      AS dividend,
  CEILING(SUM(t.quantity))                        AS quantity,
  CEILING(SUM(t.quantity) * d.dividend / 100)     AS payment,

  (@running_total := @running_total + CEILING(SUM(t.quantity) * d.dividend / 100)) AS balance

FROM
  transaction t
  JOIN (SELECT @running_total := 0) r

  INNER JOIN member m ON (m.id = t.member_id)
  INNER JOIN portfolio p ON (p.id = t.portfolio_id)
  INNER JOIN account a ON (a.id = p.account_id)
  INNER JOIN dividend d ON (d.code = t.code)
WHERE
  (m.id >= '01' AND m.id <= '02')
  AND
  d.exchange = t.exchange
  AND
  d.pdate >= NOW()
GROUP BY
  pdate, portfolio, code

Результаты здесь

+----------+--------------+--------------+-------------+--------------+-------------+-------------------+
| code     |  portfolio   |    pdate     |    dividend |     quantity |     payment |      balance      |
+----------+--------------+--------------+-------------+--------------+-------------+-------------------+
| BLND     | AJB_SIPP_CO  | 2018-05-05   | 7.52        | 1643         | 124         | 124               |
| AV.      | AJB_SIPP_CO  | 2018-05-17   | 15.88       | 2135         | 340         | 340               |
| AV.      | SFT_DEA_CO   | 2018-05-17   | 15.88       | 2318         | 369         | 369               |
| DLG      | AJB_SIPP_CO  | 2018-05-18   | 9.7         | 2732         | 266         | 266               |
| DLG      | SFT_DEA_CO   | 2018-05-18   | 9.7         | 2789         | 271         | 271               |
| SLA      | AJB_SIPP_CO  | 2018-05-23   | 13.35       | 2820         | 377         | 377               |
| SLA      | SFT_DEA_CO   | 2018-05-23   | 13.35       | 3247         | 434         | 434               |
| PHP      | AJB_SIPP_CO  | 2018-05-27   | 1.31        | 6947         | 92          | 92                |
| LLOY     | AJB_SIPP_CO  | 2018-05-29   | 2.05        | 15519        | 319         | 319               |
| LLOY     | SFT_DEA_CL   | 2018-05-29   | 2.05        | 40011        |     +----------+--------------+--------------+-------------+--------------+-------------+-------------------+

Опять же, это не дает желаемых результатов

Проблема, по-видимому, связана с тем, что при наличии нескольких платежей в одну и ту же дату он группирует баланс для всех значений <= дата строки, если у меня было уникальное поле или последовательный подсчет по строкам, чтобы избежать дублирования ключа (дата, портфолио, код) </p>

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

Дайте мне знать, если вам нужна дополнительная информация.

Большое спасибо заранее

Colin

Обновите, если я жестко закодирую портфель SFT_DEA_CO , накопленный баланс работает, см. Ниже

SELECT 
d.code AS code, 
p.name AS portfolio, 
d.pdate AS pdate,
d.dividend AS dividend, 
CEILING(SUM(t.quantity)) AS quantity,
CEILING(SUM(t.quantity) * d.dividend / 100) AS payment, 

(
SELECT 
CEILING(SUM(din.dividend * tin.quantity)/100)
FROM 
transaction tin
INNER JOIN member min ON (tin.member_id = min.id)
INNER JOIN dividend din ON (tin.code = din.code)
INNER JOIN portfolio pin ON (tin.portfolio_id = pin.id)
WHERE
(min.id >= '01' AND min.id <= '02')
AND
din.pdate <= d.pdate
AND
din.pdate >= NOW()
AND
pin.name = 'SFT_DEA_CO'
)
AS balance

FROM 
transaction t
INNER JOIN member m ON (m.id = t.member_id)
INNER JOIN portfolio p ON (p.id = t.portfolio_id)
INNER JOIN account a ON (a.id = p.account_id)
INNER JOIN dividend d ON (d.code = t.code)
WHERE  
(m.id >= '01' AND m.id <= '02')
AND
d.exchange = t.exchange 
AND 
d.pdate >= NOW()
AND
p.name = 'SFT_DEA_CO'
GROUP BY 
pdate, portfolio, code

Результаты показаны ниже, где кумулятивная работа работает, только если портфолио жестко закодировано

code    portfolio   pdate   dividend    quantity    payment     balance     
AV. SFT_DEA_CO  2018-05-17  15.88   2318    369 369 
DLG SFT_DEA_CO  2018-05-18  9.7 2789    271 639 
SLA SFT_DEA_CO  2018-05-23  13.35   3247    434 1073    
BP. SFT_DEA_CO  2018-06-23  7.67    446 35  1107    
VUKE    SFT_DEA_CO  2018-07-05  44.255  899 398 1505    
GSK SFT_DEA_CO  2018-07-13  19  2242    426 1931    
MKS SFT_DEA_CO  2018-07-14  11.9    4223    503 2433    
VOD SFT_DEA_CO  2018-08-04  8.8 12053   1061    3494    
BT.A    SFT_DEA_CO  2018-09-04  10.55   8802    929 4422    
DLG SFT_DEA_CO  2018-09-08  6.8 2789    190 4612    
BP. SFT_DEA_CO  2018-09-22  7.67    446 35  5386    
SSE SFT_DEA_CO  2018-09-22  63.9    1158    740 5386    
VUKE    SFT_DEA_CO  2018-10-04  36.046  899 325 5710    
GSK SFT_DEA_CO  2018-10-12  19  2242    426 6136    

1 Ответ

0 голосов
/ 04 мая 2018

Возможно, этот пример даст вам необходимую структуру ... Я построил одну таблицу под названием «test», которая содержит несколько столбцов, на которые вы ссылались. В примере запроса есть 2 отдельные переменные идентификации строки, поэтому вы можете подтвердить порядок обработки строк.

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

Надеюсь, это поможет.

Запрос ниже ....

    select
     @row_n := @row_n + 1 as row_n,
     row_num,
     code,
     portfolio,
     pdate,
     dividend,
     quantity,
     payment,
     balance
     from ( select
     @row_num := @row_num + 1 as row_num,
     code,
     portfolio,
     pdate,
     dividend,
     quantity,
     ceiling(dividend*quantity/100) as payment,
     @balance := ceiling(dividend*quantity/100) + if (@prev_pfl = portfolio,@balance,0) as balance,
     @prev_pfl := portfolio as prev_portfolio
    from test
    cross join
    ( select @row_num := 0, @balance := 0, @prev_pfl := '' ) as InitVarsAlias 
    order by portfolio, pdate,code) as SubQueryAlias
    cross join 
    (select @row_n := 0 ) as InitVarsAlias2 
    order by pdate,portfolio,code,row_num;

и результат ниже

    row_n   row_num     code    portfolio       pdate       dividend    quantity    payment     balance
    1       2           BLND    AJB_SIPP_CO     2018-05-05  7.52        1643        124         124
    2       3           BLND    AJB_SIPP_CO     2018-05-05  7.52        1643        124         248
    3       4           AV.     AJB_SIPP_CO     2018-05-17  15.88       2135        340         588
    4       18          AV.     SFT_DEA_CO      2018-05-17  15.88       2318        369         369
    5       5           DLG     AJB_SIPP_CO     2018-05-18  9.70        2732        266         854
    6       19          DLG     SFT_DEA_CO      2018-05-18  9.70        2789        271         640
    7       6           SLA     AJB_SIPP_CO     2018-05-23  13.35       2820        377         1231
    8       20          SLA     SFT_DEA_CO      2018-05-23  13.35       3247        434         1074
    9       7           PHP     AJB_SIPP_CO     2018-05-27  1.31        6947        92          1323
    10      8           LLOY    AJB_SIPP_CO     2018-05-29  2.05        15519       319         1642
    11      15          LLOY    SFT_DEA_CL      2018-05-29  2.05        40011       821         821
    12      24          LLOY    SFT_ISA_CO      2018-05-29  2.05        7973        164         164
    13      1           FCPT    AJB_SIPP_CL     2018-05-31  0.50        223         2           2
    14      9           FCPT    AJB_SIPP_CO     2018-05-31  0.50        5837        30          1672
    15      10          RLSEB   AJB_SIPP_CO     2018-05-31  1.80        5021        91          1763
    16      22          FCPT    SFT_ISA_CL      2018-05-31  0.50        3609        19          19
    17      23          RLSEB   SFT_ISA_CL      2018-05-31  1.80        2100        38          57
    18      25          FCPT    SFT_ISA_CO      2018-05-31  0.50        5136        26          190
    19      26          RLSEB   SFT_ISA_CO      2018-05-31  1.80        2100        38          228
    20      11          LGEN    AJB_SIPP_CO     2018-06-08  10.35       3923        407         2170
    21      16          LGEN    SFT_DEA_CL      2018-06-08  10.35       10652       1103        1924
    22      12          BP.     AJB_SIPP_CO     2018-06-23  7.67        2130        164         2334
    23      13          RDSB    AJB_SIPP_CO     2018-06-23  35.02       436         153         2487
    24      17          RDSB    SFT_DEA_CL      2018-06-23  35.02       1292        453         2377
    25      21          BP.     SFT_DEA_CO      2018-06-23  7.67        446         35          1109
    26      14          CNA     AJB_SIPP_CO     2018-06-29  8.40        7512        632         3119

Если вы хотите воссоздать мой тест в точности, вот схема таблицы, которую я использовал в своем тесте.

    CREATE TABLE `test` (
      `code` varchar(10) DEFAULT NULL,
      `portfolio` varchar(30) DEFAULT NULL,
      `pdate` date DEFAULT NULL,
      `dividend` decimal(12,2) DEFAULT NULL,
      `quantity` int(11) DEFAULT NULL,
      `payment` double(12,2) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

и вот код для его заполнения ...

    LOCK TABLES `test` WRITE;
    /*!40000 ALTER TABLE `test` DISABLE KEYS */;
    INSERT INTO `test` VALUES 
    ('BLND','AJB_SIPP_CO','2018-05-05',7.52,1643,124.00),
    ('BLND','AJB_SIPP_CO','2018-05-05',7.52,1643,124.00),
    ('AV.','AJB_SIPP_CO','2018-05-17',15.88,2135,340.00),
    ('AV.','SFT_DEA_CO','2018-05-17',15.88,2318,369.00),
    ('DLG','AJB_SIPP_CO','2018-05-18',9.70,2732,266.00),
    ('DLG','SFT_DEA_CO','2018-05-18',9.70,2789,271.00),
    ('SLA','AJB_SIPP_CO','2018-05-23',13.35,2820,377.00),
    ('SLA','SFT_DEA_CO','2018-05-23',13.35,3247,434.00),
    ('PHP','AJB_SIPP_CO','2018-05-27',1.31,6947,92.00),
    ('LLOY','AJB_SIPP_CO','2018-05-29',2.05,15519,319.00),
    ('LLOY','SFT_DEA_CL','2018-05-29',2.05,40011,821.00),
    ('LLOY','SFT_ISA_CO','2018-05-29',2.05,7973,164.00),
    ('FCPT','AJB_SIPP_CL','2018-05-31',0.50,223,2.00),
    ('FCPT','AJB_SIPP_CO','2018-05-31',0.50,5837,30.00),
    ('RLSEB','AJB_SIPP_CO','2018-05-31',1.80,5021,91.00),
    ('FCPT','SFT_ISA_CL','2018-05-31',0.50,3609,19.00),
    ('RLSEB','SFT_ISA_CL','2018-05-31',1.80,2100,38.00),
    ('FCPT','SFT_ISA_CO','2018-05-31',0.50,5136,26.00),
    ('RLSEB','SFT_ISA_CO','2018-05-31',1.80,2100,38.00),
    ('LGEN','AJB_SIPP_CO','2018-06-08',10.35,3923,407.00),
    ('LGEN','SFT_DEA_CL','2018-06-08',10.35,10652,1103.00),
    ('BP.','AJB_SIPP_CO','2018-06-23',7.67,2130,164.00),
    ('RDSB','AJB_SIPP_CO','2018-06-23',35.02,436,153.00),
    ('RDSB','SFT_DEA_CL','2018-06-23',35.02,1292,453.00),
    ('BP.','SFT_DEA_CO','2018-06-23',7.67,446,35.00),
    ('CNA','AJB_SIPP_CO','2018-06-29',8.40,7512,632.00);
    /*!40000 ALTER TABLE `test` ENABLE KEYS */;
    UNLOCK TABLES;

Затем просто запустите запрос, указанный в начале.

- сделано -

на основе приведенного выше примера, я думаю, ваш запрос будет более точно аппроксимирован следующим:

Примечание: я включил в результат внутреннее поле row_num запроса, но это не обязательно.

    SELECT 
     @row_n := @row_n + 1 as row_n,
     row_num,
     code,
     portfolio,
     pdate,
     dividend,
     quantity,
     payment,
     balance 
    from ( SELECT 
     @row_num := @row_num + 1 as row_num,
     din.code as code,
     pin.name as portfolio,
     din.pdate as pdate,
     din.dividend as dividend
     ceiling(sum(tin.quantity)) as quantity,
     ceiling(sum(din.dividend * tin.quantity)/100) as payment,
     ceiling(sum(din.dividend * tin.quantity)/100) + if(@prev_pfl = pin.name,@balance,0) as balance,
     @prev_pfl := pin.name 
    FROM 
    transaction tin
    INNER JOIN member min ON (tin.member_id = min.id)
    INNER JOIN dividend din ON (tin.code = din.code)
    INNER JOIN portfolio pin ON (tin.portfolio_id = pin.id)
    cross join
    ( select @row_num := 0, @balance := 0, @prev_pfl := '' ) as InitVarsAlias 
    WHERE
    (min.id >= '01' AND min.id = NOW()
    ORDER BY pin.name,din.pdate,din.code ) AS SubQueryAlias
    cross join
    (select @row_n := 0 ) as InitVarsAlias2 
    order by pdate,portfolio,code,row_num;

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