回答

收藏

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

技术问答 技术问答 268 人阅读 | 0 人回复 | 2023-09-14

您如何在一个日期稀疏的表与另一个日期详尽的表之间进行联接,以使稀疏日期之间的间隔取前一个稀疏日期的值?9 I6 j7 }4 r! T+ c
说明性示例:7 h: A! d' D3 U% z0 L( |$ m
PRICE table (sparse dates):
9 @; I5 ?0 e% I% m0 |0 ldate        itemid  price
+ |. W# {  A: F# C* k% `2008-12-04  1       $1
! B8 k3 y7 }6 f: }; H& h2008-12-11  1       $35 }# r" ?& i5 s  @' ?4 W
2008-12-15  1       $7( C' o0 u+ j$ l6 [$ l5 a

# i; `5 O+ r! N$ NVOLUME table (exhaustive dates):
4 Z1 [' N4 g& Y3 J, Ldate         itemid  volume_amt# `% w+ s; i- K
2008-12-04   1       12345
+ J2 x5 a/ b, @4 d! r/ E4 ]* x2008-12-05   1       234564 P1 i& f& B; Y$ z6 g1 }. ?1 Y
2008-12-08   1       34567+ Z4 s" o; ~% M5 Q
2008-12-09   1       ...- U: j6 o! s+ c+ Z6 f8 U+ A- o8 c9 }1 G
2008-12-10   1; d1 u2 o" Q! b! p  m5 ~
2008-12-11   1
5 U- X3 u* N" S# W+ G& f3 Z2008-12-12   1' @6 f1 ?" h7 N/ r, p0 c
2008-12-15   1
: g7 d5 _0 Q3 n5 Z2008-12-16   1' F( M7 s. Z% a* n& e
2008-12-17   1
5 V: ^* m0 Z. @3 N: M# p! h2008-12-18   16 s: v. n2 b( z- V3 P4 z3 U
所需结果:$ Y" t+ ?, i: g) o
date       price  volume_amt
, j# |. X, s/ p) Y* E2008-12-04 $1     12345
5 ]  o9 Y) q$ L$ b- B& _2008-12-05 $1     234561 y6 a/ h& Q) @1 W5 A: K
2008-12-08 $1     34567
  B$ X- p& w# R1 F8 Q2008-12-09 $1     ...
7 e+ P5 I. \: Z/ J2008-12-10 $1; `9 b1 u8 R8 U& W& w, N4 Q6 G
2008-12-11 $3; J  R, V9 s# }8 A
2008-12-12 $3
. R0 `) p7 r" p0 w( ~% d! Y2008-12-15 $7
- J+ {6 V' I$ M- l/ f* k2008-12-16 $7
8 u$ u3 V+ W# l% N5 K9 ]7 v2008-12-17 $7, f* h7 `" V3 K) r  [3 w7 E
2008-12-18 $7# m' J1 {* T7 `3 h6 Y# ~5 e, D
更新:6 {5 F! f% D% D5 {
几个人提出了可以完成所需结果的相关子查询。(相关子查询=包含对外部查询的引用的子查询。)
' L# V- }8 e' G这将起作用;但是,我应该注意到,我使用的平台是MySQL,其相关子查询的优化效果很差。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。有没有使用相关子查询的任何方法?
9 K( J) M" _7 F, n, O0 G' f( x2 u               
, |. ~. {- J9 U1 d0 h解决方案:. |" M" U! |, s) |5 k) ]! S/ x, r
                7 M+ }. g/ _2 D

! b6 y2 d% u: }" C6 ~, I6 c
9 m8 G2 c  u4 \, [2 j                这不像向稀疏表中的单个LEFT OUTER JOIN那样简单,因为您希望用最新的价格填充外部联接留下的NULL。; K$ z2 ^, u, A3 C6 u) }$ W
EXPLAIN SELECT v.`date`, v.volume_amt, p1.item_id, p1.price
3 l; D- s! ^7 e9 uFROM Volume v JOIN Price p10 r; M. M1 a& k
  ON (v.`date` >= p1.`date` AND v.item_id = p1.item_id)) n) Q9 G; i, [: t! p
LEFT OUTER JOIN Price p28 G; A) p  f  b( o; c6 K( E! @
  ON (v.`date` >= p2.`date` AND v.item_id = p2.item_id3 S1 p5 Y& i/ P* _
    AND p1.`date` 该查询将“成交量”与“价格”中所有较早的行匹配,然后使用另一个联接来确保我们仅找到最新的价格。
0 F# @* N! }. z- ]& p" }我在MySQL 5.0.51上进行了测试。它既不使用相关子查询,也不使用分组依据。  b, [+ H: c8 W1 ?0 Q
编辑: 更新查询以匹配item_id以及日期。这似乎也可行。我在(date)和上创建了一个索引,(date,
( A$ A7 x* c% B* m" M& Kitem_id)并且EXPLAIN计划是相同的。(item_id, date)在这种情况下,索引为on可能更好。这是EXPLAIN的输出:/ K  q! A' E; Z9 ^
+----+-------------+-------+------+---------------+---------+---------+-----------------+------+--------------------------------------+
/ g% E- _$ e0 g% k% _! \| id | select_type | table | type | possible_keys | key     | key_len | ref             | rows | Extra                                |. O$ ~, |0 d$ H3 @8 M$ ?
+----+-------------+-------+------+---------------+---------+---------+-----------------+------+--------------------------------------+5 `8 B. `1 J/ Z: ^) S
|  1 | SIMPLE      | p1    | ALL  | item_id       | NULL    | NULL    | NULL            |    6 |                                      | , \( j# y/ q1 x, a& n- l1 C
|  1 | SIMPLE      | v     | ref  | item_id       | item_id | 22      | test.p1.item_id |    3 | Using where                          | : p/ U9 b* C- C
|  1 | SIMPLE      | p2    | ref  | item_id       | item_id | 22      | test.v.item_id  |    1 | Using where; Using index; Not exists | ' W# R! k2 X. u
+----+-------------+-------+------+---------------+---------+---------+-----------------+------+--------------------------------------+' b9 V; p, R/ E! z5 Z! c
但是我的数据集很小,优化可能取决于较大的数据集。您应该尝试使用更大的数据集来分析优化。
- [5 F3 o, T0 o. A( Z编辑: 我之前粘贴了错误的EXPLAIN输出。上面的一个已更正,并且显示了(item_id, date)索引的更好使用。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则