2015-10-06 41 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