在SQL中需要有关复杂Join语句的帮助

ʞɔı*_*ɔıu 3 sql greatest-n-per-group

如何在具有稀疏日期数的表和另一个具有详尽日期数的表之间进行连接,以使稀疏日期之间的间隙采用上一个稀疏日期的值?

说明性示例:

PRICE table (sparse dates):
date        itemid  price
2008-12-04  1       $1
2008-12-11  1       $3
2008-12-15  1       $7


VOLUME table (exhaustive dates):
date         itemid  volume_amt
2008-12-04   1       12345
2008-12-05   1       23456
2008-12-08   1       34567
2008-12-09   1       ...
2008-12-10   1
2008-12-11   1
2008-12-12   1
2008-12-15   1
2008-12-16   1
2008-12-17   1
2008-12-18   1
Run Code Online (Sandbox Code Playgroud)

期望的结果:

date       price  volume_amt
2008-12-04 $1     12345
2008-12-05 $1     23456
2008-12-08 $1     34567
2008-12-09 $1     ...
2008-12-10 $1
2008-12-11 $3
2008-12-12 $3
2008-12-15 $7
2008-12-16 $7
2008-12-17 $7
2008-12-18 $7
Run Code Online (Sandbox Code Playgroud)

更新:

有几个人建议使用相关的子查询来完成所需的结果.(Correlated subquery =包含对外部查询的引用的子查询.)

这将有效; 但是,我应该注意到我使用的平台是MySQL,其相关子查询的优化程度很低.没有使用相关子查询的任何方法吗?

Bil*_*win 7

这并不像稀疏表的单个LEFT OUTER JOIN那么简单,因为您希望外部联接留下的NULL用最近的价格填充.

EXPLAIN SELECT v.`date`, v.volume_amt, p1.item_id, p1.price
FROM Volume v JOIN Price p1
  ON (v.`date` >= p1.`date` AND v.item_id = p1.item_id)
LEFT OUTER JOIN Price p2
  ON (v.`date` >= p2.`date` AND v.item_id = p2.item_id
    AND p1.`date` < p2.`date`)
WHERE p2.item_id IS NULL;
Run Code Online (Sandbox Code Playgroud)

此查询将Volume与Price之前的所有行匹配,然后使用另一个联接以确保我们只查找最近的价格.

我在MySQL 5.0.51上测试了这个.它既不使用相关子查询也不使用group by.

编辑:更新了查询以匹配item_id和日期.这似乎也有效.我创建了索引(date)和索引,(date, item_id)并且EXPLAIN计划是相同的.(item_id, date)在这种情况下,索引可能更好.这是EXPLAIN输出:

+----+-------------+-------+------+---------------+---------+---------+-----------------+------+--------------------------------------+
| id | select_type | table | type | possible_keys | key     | key_len | ref             | rows | Extra                                |
+----+-------------+-------+------+---------------+---------+---------+-----------------+------+--------------------------------------+
|  1 | SIMPLE      | p1    | ALL  | item_id       | NULL    | NULL    | NULL            |    6 |                                      | 
|  1 | SIMPLE      | v     | ref  | item_id       | item_id | 22      | test.p1.item_id |    3 | Using where                          | 
|  1 | SIMPLE      | p2    | ref  | item_id       | item_id | 22      | test.v.item_id  |    1 | Using where; Using index; Not exists | 
+----+-------------+-------+------+---------------+---------+---------+-----------------+------+--------------------------------------+
Run Code Online (Sandbox Code Playgroud)

但是我的数据集很小,优化可能依赖于更大的数据集.您应该尝试使用更大的数据集分析优化.

编辑:之前我粘贴了错误的EXPLAIN输出.上面的一个更正,并显示更好地使用(item_id, date)索引.