当前位置: 首页 > 面试题库 >

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

危斯伯
2023-03-14
问题内容

您如何在一个日期稀疏的表与另一个日期详尽的表之间进行联接,以使稀疏日期之间的间隔取前一个稀疏日期的值?

说明性示例:

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

所需结果:

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

更新:

几个人提出了可以完成所需结果的相关子查询。(相关子查询=包含对外部查询的引用的子查询。)

这将起作用;但是,我应该注意到,我使用的平台是MySQL,其相关子查询的优化效果很差。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。有没有使用相关子查询的任何方法?


问题答案:

这不像向稀疏表中的单个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;

该查询将“成交量”与“价格”中所有较早的行匹配,然后使用另一个联接来确保我们仅找到最新的价格。

我在MySQL 5.0.51上进行了测试。它既不使用相关子查询,也不使用分组依据。

编辑: 更新查询以匹配item_id以及日期。这似乎也可行。我在(date)和上创建了一个索引,(date, item_id)并且EXPLAIN计划是相同的。(item_id, date)在这种情况下,索引为on可能更好。这是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 | 
+----+-------------+-------+------+---------------+---------+---------+-----------------+------+--------------------------------------+

但是我的数据集很小,优化可能取决于较大的数据集。您应该尝试使用更大的数据集来分析html" target="_blank">优化。

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



 类似资料:
  • 问题内容: 好吧,我可能也已在较早之前发布了此内容,但到目前为止仍找不到答案,因此请帮助我解决这个问题。 我的数据库结构: ATT (表) Act_ID(PK) Assigned_To_ID(FK,请参阅) Project_ID(FK,请参阅) Product_ID(FK,请参阅) 状态(可以是) 产品表 产品编号(PK) 产品名称 项目表 Project_ID(PK) 项目名 员工表 Emp_I

  • 我在代码中遇到了一些设计问题。我目前正在为一个游戏编写原型Java但是我对我所做的选择不满意。目前我的游戏有几个类:圆形、圆形集和组件(基本上是主类)。这些类之间的关系如下: 1圆形集可以有多个圆形,每个圆形集都需要知道它在哪个圆形集中。 有人能帮我举一些收藏的例子吗?什么最适合我? 提前感谢!

  • 问题内容: 我正在尝试在子句中构建case / if语句。 问题在于该列包含文本和数字。我要与之比较的列是一个整数。 有没有一种方法可以检测列是否包含字符或数字,然后将其设置为0,然后将其设置为0? 这是一个伪查询可以帮助您: 问题答案: 您正在寻找IsNumeric,但它并不总是有效(+,-和。是数字),因此您需要使用GBN所描述的解决方案,即在您的varchar中添加.0e0

  • 问题内容: 我正在尝试构建我的第一个Boost.Python示例。 编辑:正如@cdhowie所指出的,Python开发标头丢失了。我已经找到并包含了必需的头文件。现在链接器在抱怨: 我已经链接到-lpython3.3m -lboost_python-mt -lpython3.3-还有什么丢失的? 编辑:我想我已经链接到python3.3-config列出的所有内容。由于缺少符号,链接仍然不起作用

  • 这是主平衡分区 我正尝试通过以这种方式添加这两个分区来更新

  • 问题内容: 我想从一个名为Sorels的表更新一个名为的表。它们之间的链接是的等于Sorels表的。这是我对Merge语句的第一次尝试,并且我正在尝试学习语法。 运行此命令时,出现以下错误: 错误10/22/2009 1:38:51 PM 0:00:00.000 SQL Server数据库错误:关键字’ON’附近的语法不正确。46 0 添加的信息* 在建议了第一个修复程序之后,代码如下: 现在我得