在LEFT JOIN中克服“至少一次”条件

时间:2010-11-12 12:16:28

标签: mysql join query-optimization left-join

我有以下两个表quote(date,market,ticker,close)scenario(date1,date2,period,market,ticker,ratio)。我编写了以下LEFT JOIN查询,除了一个问题外,它还能做我想要的事情:

SELECT  S.date1 AS date1, 
        S.date2 AS date2,
        S.period AS period,
        Q.market AS market,
        Q.ticker AS ticker,
        Q.close * EXP(S.ratio) AS scenario

FROM portfolio.quote Q  LEFT JOIN  portfolio.scenario S 

      ON Q.market = S.market AND
         Q.ticker = S.ticker AND
         S.date1 >= '2010-06-01' AND
         S.date2 <= '2010-07-01' AND
         S.period = 'WEEK'

WHERE Q.date = '2010-07-01' 
ORDER BY S.date1, S.date2, S.period, Q.market, Q.ticker

上一个查询返回结果,并且当报价表中的每个(市场,股票代码)与场景表中的等价物(市场,股票代码)不匹配时,会为属于场景表的列添加一个NULL值的行就这样:

date1, date2, period, market , ticker, scenario
NULL , NULL , NULL  , 'sp500', 'QEP' , NULL

对于'2010-06-01'和'2010-07-01'之间的期间'周',可能有许多不匹配的行('sp500','QEP')但只有一行代表这个在属于方案表的列中具有NULL值的事实。更不用说,在这些结果中,(市场,股票代码)有许多不匹配的行,但至少存在一个匹配,因此查询不会为这些行返回NULL值。

我想要做的是,例如,如果Q.date ='2010-07-01'为报价表返回500行,则会有500 *(DISTINCT date1,date,period)。仅当以下条件不匹配时,方案列中包含NULL值:

Q.market = S.market AND
Q.ticker = S.ticker

因此,例如,NULL结果看起来像这样:

date1        , date2        , period  , market , ticker, scenario
'2010-06-01' , '2010-06-08' , 'WEEK'  , 'sp500', 'QEP' , NULL
'2010-06-08' , '2010-06-15' , 'WEEK'  , 'sp500', 'QEP' , NULL
'2010-06-15' , '2010-06-23' , 'WEEK'  , 'sp500', 'A'   , NULL

另一个示例,例如,与引用表中的(market,ticker,close)匹配的Q.date = '2010-07-01'行是:

('sp','A',1)
('sp','AA',2)

符合条件的(date1,date2,period,market,ticker,ratio)

     S.date1 >= '2010-06-01' AND
     S.date2 <= '2010-07-01' AND
     S.period = 'WEEK'

是:

('2010-06-01','2010-06-08','WEEK','sp','A',0.43)
('2010-06-01','2010-06-08','WEEK','sp','AA',0.21)

('2010-06-08','2010-06-20','WEEK','sp','A',0.49)

('2010-06-20','2010-06-27','WEEK','sp','A',0.46)
('2010-06-20','2010-06-27','WEEK','sp','B',0.23)

然后我的查询结果应该返回

('2010-06-01','2010-06-08','WEEK','sp','A',1*EXP(0.43))
('2010-06-01','2010-06-08','WEEK','sp','AA',2*EXP(0.21))

('2010-06-08','2010-06-20','WEEK','sp','A',1*EXP(0.49))
('2010-06-08','2010-06-20','WEEK','sp','AA',NULL)

('2010-06-20','2010-06-27','WEEK','sp','A',1*EXP(0.46))
('2010-06-20','2010-06-27','WEEK','sp','AA',NULL)

这种事情在MySQL中是否可行?,非常感谢任何帮助:)

1 个答案:

答案 0 :(得分:1)

由于您正在使用LEFT联接,因此即使与ON条件的其他表(方案)没有完全匹配,也会显示FROM表的(引用)行。其他表中的列只是替换为NULL。

但是,您一直想要做的是显示场景表中的所有行而不是引用表。所以我建议您使用RIGHT join或将查询部分替换为
    FROM portfolio.scenario S LEFT JOIN portfolio.quote Q

希望能解决你的问题。