2015-10-06 93 views
3

我有以下两个表:SQL查询改变

1)表名:周期

+----------+ 
| PeriodID | 
+----------+ 
|  1 | 
|  2 | 
|  3 | 
|  4 | 
+----------+ 

2)表名称:值

+-------------+--------+ 
| StartPeriod | Amount | 
+-------------+--------+ 
|   1 | 100 | 
|   3 | 200 | 
+-------------+--------+ 

第一个表表示时间期间,如月。第二张表格表示每个月的金额,但仅限于与上个月不同的金额。金额从100开始,第2期保持在100,然后在第3期开始时跳到200,之后保持在200。

我需要一个查询(MySQL的)返回的金额每个时期,像这样:

+----------+--------+ 
| PeriodID | Amount | 
+----------+--------+ 
|  1 | 100 | 
|  2 | 100 | 
|  3 | 200 | 
|  4 | 200 | 
+----------+--------+ 

所以查询将返回最新StartPeriod的数量,在值表使用小于或等于PeriodID。例如,对于PeriodID 2,它将返回Amount for StartPeriod 1,因为StartPeriod2没有值,1是小于或等于2的最大值,该值在值表中具有Amount。

(对不起,表格太难看了)

谢谢!

+0

为什么不喜欢的事情startPeriod = 2,金额为100添加记录?看起来有点傻,不得不依赖更复杂的查询结构,因为您尚未设置数据以允许有效查询。 –

回答

2

您可以使用相关子查询做到这一点:

SELECT PeriodID, 
     @amount := IF(Amount IS NOT NULL, Amount, @amount) AS Amount 
FROM ( 
    SELECT PeriodID, Amount 
    FROM Period AS p 
    LEFT JOIN Value AS v ON p.PeriodID = v.StartPeriod) AS t 
CROSS JOIN (SELECT @amount := -1) AS var 
ORDER BY PeriodID 

Demo here

:相对于相关联的子查询

SELECT PeriodID, 
     (SELECT Amount 
     FROM Value 
     WHERE StartPeriod <= PeriodID 
     ORDER BY StartPeriod DESC LIMIT 1) AS Amount 
FROM Period AS p 

Demo here

使用变量可能执行得更好

+0

这两个工作都很完美。但是,我在第二个问题后遇到了麻烦,你能解释一下吗?在使用@amount定义@amount变量时,IF语句如何工作? -1做什么? – gcblmnop

+0

@gcblmnop变量以逐行为基础工作。行订单处理由'ORDER BY'子句定义。因此,最初“@ amount”被初始化为“-1”。一旦满足NOT NULL值,IF函数将'Amount'赋值给'@ amount',否则'@ amount'被设置为等于* previous *行的'@ amount'。通过这种方式,NOT NULL'Amount'值向下传播到下一行,该行具有NOT NULL'Amount'值。 –

1

一个简单的子选择选择用于最高startperiod较低或期间-ID值等于可以achive说:

select 
    periodid, 
    (select amount from value where startperiod <= periodid order by startperiod desc limit 1) 
from period 
order by periodid; 

http://sqlfiddle.com/#!9/9f29c/3