在内部联接中迭代使用MySQL LAG()

在内部联接中迭代使用MySQL LAG(),mysql,mysql-8.0,Mysql,Mysql 8.0,我有两个表,我需要在一个循环中迭代地连接它们,以创建值来填充其中一个表我主要是寻找最干净的方法来进行单周期移位联接,详情如下。下面两个输入表的示例: DROP TABLE IF EXISTS holdings; CREATE TABLE holdings (date DATE NOT NULL ,ticker CHAR(4) NOT NULL ,wgt DECIMAL(5,2) ,PRIMARY KEY(date,ticker) ); INSERT INTO holdings VALUES

我有两个表,我需要在一个循环中迭代地连接它们,以创建值来填充其中一个表我主要是寻找最干净的方法来进行单周期移位联接,详情如下。下面两个输入表的示例:

DROP TABLE IF EXISTS holdings;

CREATE TABLE holdings
(date DATE NOT NULL
,ticker CHAR(4) NOT NULL
,wgt DECIMAL(5,2)
,PRIMARY KEY(date,ticker)
);

INSERT INTO holdings VALUES
('2019-03-29','MTUM',0.2),
('2019-03-29','QUAL',0.2),
('2019-03-29','SIZE',0.2),
('2019-03-29','USMV',0.2),
('2019-03-29','VLUE',0.2),
('2019-06-28','MTUM',0.2),
('2019-06-28','QUAL',0.2),
('2019-06-28','SIZE',0.2),
('2019-06-28','USMV',0.2),
('2019-06-28','VLUE',0.2);

DROP TABLE IF EXISTS returns;

CREATE TABLE returns
(monthEnd  DATE NOT NULL
,ticker CHAR(4) NOT NULL
,ret DECIMAL(11,8) NOT NULL
,PRIMARY KEY(monthend,ticker)
);

INSERT INTO returns VALUES
('2019-03-29',  'USMV' ,   0.02715291),
('2019-03-29',  'SIZE' ,   0.00512113),
('2019-03-29',  'VLUE' ,  -0.00943159),
('2019-03-29',  'MTUM' ,   0.02118479),
('2019-03-29',  'QUAL' ,   0.02533432),
('2019-04-30',  'USMV' ,   0.02176873),
('2019-04-30',  'SIZE' ,   0.03818616),
('2019-04-30',  'VLUE' ,   0.03418481),
('2019-04-30',  'MTUM' ,   0.02255305),
('2019-04-30',  'QUAL' ,   0.03794464),
('2019-05-31',  'VLUE' ,  -0.09601646),
('2019-05-31',  'MTUM' ,  -0.02196844),
('2019-05-31',  'QUAL' ,  -0.06582526),
('2019-05-31',  'USMV' ,  -0.01614514),
('2019-05-31',  'SIZE' ,  -0.06918445),
('2019-06-28',  'QUAL' ,   0.07073081),
('2019-06-28',  'VLUE' ,   0.09571038),
('2019-06-28',  'MTUM' ,   0.06121113),
('2019-06-28',  'USMV' ,   0.04984654),
('2019-06-28',  'SIZE' ,   0.07531133),
('2019-07-31',  'QUAL' ,   0.013775  ),
('2019-07-31',  'MTUM' ,   0.01795953),
('2019-07-31',  'SIZE' ,   0.01208791),
('2019-07-31',  'VLUE' ,   0.01601182),
('2019-07-31',  'USMV' ,   0.01668555);
这里的第一步是将holdings加入到returns,将日期对齐移动一个周期,这样第一次迭代的输出如下所示:

date    portName    ticker  wgt monthEnd    ticker  ret
2019-03-29  test    MTUM    0.2 2019-04-30  MTUM    0.02255305
2019-03-29  test    QUAL    0.2 2019-04-30  QUAL    0.03794464
2019-03-29  test    SIZE    0.2 2019-04-30  SIZE    0.03818616
2019-03-29  test    USMV    0.2 2019-04-30  USMV    0.02176873
2019-03-29  test    VLUE    0.2 2019-04-30  VLUE    0.03418481
date    portName    ticker  wgt
2019-04-30  test    MTUM    0.201442484998052
2019-04-30  test    QUAL    0.202261035805858
2019-04-30  test    SIZE    0.198273711216605
2019-04-30  test    USMV    0.202619777232855
2019-04-30  test    VLUE    0.19540299074663
此时,
wgt
ret
组合在一起,为每个条目提供一个新的
wgt
(为了简单起见,省略了计算)。这些新权重被插入到holdings表中,这些记录如下所示:

date    portName    ticker  wgt monthEnd    ticker  ret
2019-03-29  test    MTUM    0.2 2019-04-30  MTUM    0.02255305
2019-03-29  test    QUAL    0.2 2019-04-30  QUAL    0.03794464
2019-03-29  test    SIZE    0.2 2019-04-30  SIZE    0.03818616
2019-03-29  test    USMV    0.2 2019-04-30  USMV    0.02176873
2019-03-29  test    VLUE    0.2 2019-04-30  VLUE    0.03418481
date    portName    ticker  wgt
2019-04-30  test    MTUM    0.201442484998052
2019-04-30  test    QUAL    0.202261035805858
2019-04-30  test    SIZE    0.198273711216605
2019-04-30  test    USMV    0.202619777232855
2019-04-30  test    VLUE    0.19540299074663
下一步是应用与前面相同的程序,取这些权重,结合一个周期移位回报,生成如下输出:

date    portName    ticker  wgt monthEnd    ticker  ret
2019-04-30  test    MTUM    0.201442484998052   2019-05-31  MTUM    -0.02196844
2019-04-30  test    QUAL    0.202261035805858   2019-05-31  QUAL    -0.06582526
2019-04-30  test    SIZE    0.198273711216605   2019-05-31  SIZE    -0.06918445
2019-04-30  test    USMV    0.202619777232855   2019-05-31  USMV    -0.01614514
2019-04-30  test    VLUE    0.19540299074663    2019-05-31  VLUE    -0.09601646
date    portName    ticker  wgt
2019-03-29  test    MTUM    0.2
2019-03-29  test    QUAL    0.2
2019-03-29  test    SIZE    0.2
2019-03-29  test    USMV    0.2
2019-03-29  test    VLUE    0.2
2019-04-30  test    MTUM    0.201442484998052
2019-04-30  test    QUAL    0.202261035805858
2019-04-30  test    SIZE    0.198273711216605
2019-04-30  test    USMV    0.202619777232855
2019-04-30  test    VLUE    0.19540299074663
2019-05-31  test    MTUM    0.205430582
2019-05-31  test    QUAL    0.201024226
2019-05-31  test    SIZE    0.198113682
2019-05-31  test    USMV    0.204236958
2019-05-31  test    VLUE    0.205066864
2019-06-28  test    MTUM    0.2
2019-06-28  test    QUAL    0.2
2019-06-28  test    SIZE    0.2
2019-06-28  test    USMV    0.2
2019-06-28  test    VLUE    0.2
我们再次组合
wgt
ret
以确定新的
wgt
值,并将其插入控股表中

这将持续到所有日期,直到我们到达日期列表的末尾(鉴于上述示例,holdings表中的最后一个条目将为
date
2019-07-31)

需要注意的是,此过程用于填充holdings表,除非已经存在日期条目。换句话说,我们将对4/30、5/31和7/31执行此过程,但将保留6/28记录,如holdings表所示

所需的样本输出(对于子集)如下所示:

date    portName    ticker  wgt monthEnd    ticker  ret
2019-04-30  test    MTUM    0.201442484998052   2019-05-31  MTUM    -0.02196844
2019-04-30  test    QUAL    0.202261035805858   2019-05-31  QUAL    -0.06582526
2019-04-30  test    SIZE    0.198273711216605   2019-05-31  SIZE    -0.06918445
2019-04-30  test    USMV    0.202619777232855   2019-05-31  USMV    -0.01614514
2019-04-30  test    VLUE    0.19540299074663    2019-05-31  VLUE    -0.09601646
date    portName    ticker  wgt
2019-03-29  test    MTUM    0.2
2019-03-29  test    QUAL    0.2
2019-03-29  test    SIZE    0.2
2019-03-29  test    USMV    0.2
2019-03-29  test    VLUE    0.2
2019-04-30  test    MTUM    0.201442484998052
2019-04-30  test    QUAL    0.202261035805858
2019-04-30  test    SIZE    0.198273711216605
2019-04-30  test    USMV    0.202619777232855
2019-04-30  test    VLUE    0.19540299074663
2019-05-31  test    MTUM    0.205430582
2019-05-31  test    QUAL    0.201024226
2019-05-31  test    SIZE    0.198113682
2019-05-31  test    USMV    0.204236958
2019-05-31  test    VLUE    0.205066864
2019-06-28  test    MTUM    0.2
2019-06-28  test    QUAL    0.2
2019-06-28  test    SIZE    0.2
2019-06-28  test    USMV    0.2
2019-06-28  test    VLUE    0.2
我的基本方法是在唯一的日期列表上使用循环,首先检查“currentDate”值是否已经在holdings表中,然后在进行所述计算之前加入以最干净的方式专门查找输入,以执行上面提到的单周期移位联接。我来自SQL Server,在那里我通常会创建一个虚拟“rowNum”列,我可以使用它(即a.rowNum=b.rowNum+1)进行移位。想知道是否有一种方法可以在连接中使用LAG()(或其他运算符),或者是否有另一种方法更干净


我认为没有更干净的方法(即,非基于循环的方法),因为每组条目都依赖于最后一个。欢迎对该方法的其他想法。

考虑以下事项;我仍然在使用8.0之前版本的MySQL(我知道),所以这里没有窗口功能

DROP TABLE IF EXISTS holdings;

CREATE TABLE holdings
(date DATE NOT NULL
,ticker CHAR(4) NOT NULL
,wgt DECIMAL(5,2)
,PRIMARY KEY(date,ticker)
);

INSERT INTO holdings VALUES
('2019-03-29','MTUM',0.2),
('2019-03-29','QUAL',0.2),
('2019-03-29','SIZE',0.2),
('2019-03-29','USMV',0.2),
('2019-03-29','VLUE',0.2),
('2019-06-28','MTUM',0.2),
('2019-06-28','QUAL',0.2),
('2019-06-28','SIZE',0.2),
('2019-06-28','USMV',0.2),
('2019-06-28','VLUE',0.2);

DROP TABLE IF EXISTS returns;

CREATE TABLE returns
(monthEnd  DATE NOT NULL
,ticker CHAR(4) NOT NULL
,ret DECIMAL(11,8) NOT NULL
,PRIMARY KEY(monthend,ticker)
);

INSERT INTO returns VALUES
('2019-03-29',  'USMV' ,   0.02715291),
('2019-03-29',  'SIZE' ,   0.00512113),
('2019-03-29',  'VLUE' ,  -0.00943159),
('2019-03-29',  'MTUM' ,   0.02118479),
('2019-03-29',  'QUAL' ,   0.02533432),
('2019-04-30',  'USMV' ,   0.02176873),
('2019-04-30',  'SIZE' ,   0.03818616),
('2019-04-30',  'VLUE' ,   0.03418481),
('2019-04-30',  'MTUM' ,   0.02255305),
('2019-04-30',  'QUAL' ,   0.03794464),
('2019-05-31',  'VLUE' ,  -0.09601646),
('2019-05-31',  'MTUM' ,  -0.02196844),
('2019-05-31',  'QUAL' ,  -0.06582526),
('2019-05-31',  'USMV' ,  -0.01614514),
('2019-05-31',  'SIZE' ,  -0.06918445),
('2019-06-28',  'QUAL' ,   0.07073081),
('2019-06-28',  'VLUE' ,   0.09571038),
('2019-06-28',  'MTUM' ,   0.06121113),
('2019-06-28',  'USMV' ,   0.04984654),
('2019-06-28',  'SIZE' ,   0.07531133),
('2019-07-31',  'QUAL' ,   0.013775  ),
('2019-07-31',  'MTUM' ,   0.01795953),
('2019-07-31',  'SIZE' ,   0.01208791),
('2019-07-31',  'VLUE' ,   0.01601182),
('2019-07-31',  'USMV' ,   0.01668555);

SELECT a.date
     , a.ticker a_ticker
     , a.wgt
     , b.monthend
     , b.ticker b_ticker
     , b.ret
  FROM 
     ( SELECT h.*
            , MIN(monthend) monthend 
         FROM holdings h 
         LEFT -- if appropriate
         JOIN returns r 
           ON r.monthend > h.date 
          AND r.ticker = h.ticker 
        GROUP 
           BY h.date
            , h.ticker
     ) a 
  LEFT -- if appropriate
  JOIN returns b 
    ON b.monthend = a.monthen
d AND b.ticker = a.ticker;
+------------+--------+------+------------+------------+--------+------------+
| date       | ticker | wgt  | monthend   | monthEnd   | ticker | ret        |
+------------+--------+------+------------+------------+--------+------------+
| 2019-03-29 | MTUM   | 0.20 | 2019-04-30 | 2019-04-30 | MTUM   | 0.02255305 |
| 2019-03-29 | QUAL   | 0.20 | 2019-04-30 | 2019-04-30 | QUAL   | 0.03794464 |
| 2019-03-29 | SIZE   | 0.20 | 2019-04-30 | 2019-04-30 | SIZE   | 0.03818616 |
| 2019-03-29 | USMV   | 0.20 | 2019-04-30 | 2019-04-30 | USMV   | 0.02176873 |
| 2019-03-29 | VLUE   | 0.20 | 2019-04-30 | 2019-04-30 | VLUE   | 0.03418481 |
| 2019-06-28 | MTUM   | 0.20 | 2019-07-31 | 2019-07-31 | MTUM   | 0.01795953 |
| 2019-06-28 | QUAL   | 0.20 | 2019-07-31 | 2019-07-31 | QUAL   | 0.01377500 |
| 2019-06-28 | SIZE   | 0.20 | 2019-07-31 | 2019-07-31 | SIZE   | 0.01208791 |
| 2019-06-28 | USMV   | 0.20 | 2019-07-31 | 2019-07-31 | USMV   | 0.01668555 |
| 2019-06-28 | VLUE   | 0.20 | 2019-07-31 | 2019-07-31 | VLUE   | 0.01601182 |
+------------+--------+------+------------+------------+--------+------------+

冲洗并重复。

period(句号)只是序列中的下一个日期?@草莓:没错。