我在使用 postgresql 9.5 的“LEFT JOIN LATERAL”函数时遇到了一些困难。
在我的表中,有“ID”、“DATE”、“CODE”三列。一个人 (ID) 有多个行,如下所示。ID 数为 362,总行数约为 2500000。
ID / DATE / CODE
1 / 20020101 / drugA
1 / 20020102 / drugA
1 / 20020103 / drugB
1 / 20020104 / drugA
1 / 20020105 / drugA
1 / 20020106 / drugB
1 / 20020107 / drugA
2 / ... / ...
我需要总结药物 A 在药物 B 的第一天和最后一天之间使用的信息。
在上述情况下,ID(1)[在20020103~20020106之间;用药期B].
1 / 20020104 / drugA
1 / 20020105 / drugA
为了完成这项工作,我使用“LEFT LATERAL JOIN”编写 SQL 代码,如下所示。
SELECT * FROM (SELECT ID, min(DATE) as start_date, max(DATE) as end_date from MAIN_TABLE WHERE CODE = 'drugA' GROUP BY ID) AA
LEFT JOIN LATERAL (SELECT ID, COUNT(ID) as no_tx, min(DATE) as fday_tx, max(DATE) lday_tx from MAIN_TABLE WHERE CODE = 'drugB' AND DATE > AA.start_date AND DATE < AA.end_date GROUP BY ID) as BB USING(ID);
只有 362 个人 ID,但这个 postgresql 代码大约需要 2 分钟。
它太慢了。因此,我尝试了另一个使用子查询的 SQL 代码。
SELECT * FROM (SELECT ID, min(DATE) as start_date, max(DATE) as end_date from MAIN_TABLE WHERE CODE ='drugA' GROUP BY ID) AA
LEFT JOIN (
SELECT ID, COUNT(ID) as no_tx, min(DATE) as fday_tx, max(DATE) lday_tx FROM (SELECT ID, DATE, CODE FROM MAIN_TABLE) BB
LEFT JOIN (SELECT ID, min(DATE) as start_date, max(DATE) as end_date from MAIN_TABLE WHERE CODE ='drugA' GROUP BY ID) CC USING (ID)
WHERE CODE = 'drugB' and DATE > start_date and DATE < end_date GROUP BY ID
) DD USING (ID);
这段代码并不简单,但非常快(只需 1.6 秒)。
当我比较两个代码的解释时,第二个代码使用哈希连接,但第一个代码没有。
我可以得到一些提示,以更有效地改进具有“左横向连接”功能的第一个代码吗?