2014-01-30 24 views
2

我有以下查詢:從一組數據中生成每日記錄

SELECT C.DateValue, T.CustomerId, T.Balance 
FROM Calendar C 
CROSS APPLY (
    SELECT TOP(1) StartDate, CustomerId, Balance 
    FROM TestData B 
    WHERE B.StartDate <= C.DateValue 
    ORDER BY StartDate DESC 
) AS T 
WHERE C.DateValue BETWEEN '1/1/2014' AND '1/14/2014' 
ORDER BY CustomerId, DateValue 

這需要像一組數據:

CustomerId | StartDate | EndDate | Balance 

123 | 1/1/2014 | 1/3/2014 | 2000 
123 | 1/3/2014 | 1/10/2014 | 1000 
123 | 1/10/2014 | null | 500 

並將其轉換爲:

CustomerId | Date | Balance 

123 | 1/1/2014 | 2000 
123 | 1/2/2014 | 2000 
123 | 1/3/2014 | 1000 
123 | 1/4/2014 | 1000 
123 | 1/5/2014 | 1000 
... 

我遇到的問題是,它只適用於有一個CustomerId。只要我在列表中添加另一個。我試圖找出一種方式來改變這個查詢,以支持數據集中任意數量的CustomerIds。我可以通過查詢像這樣實現:

SELECT C.DateValue, T.CustomerId , T.Balance 
FROM Calendar C 
INNER JOIN TestData T on C.DateValue >= T.DataStartDate 
    AND (C.DateValue < T.EndDate OR T.EndDate IS NULL) 
WHERE C.DateValue BETWEEN '1/1/2014' AND '1/14/2014' 

但上面的查詢是非常低效的,當我將其加入包含數百萬客戶的我的實際表。 如何改變我的查詢或寫一個查詢來完成將我的數據擴展到每日列表的目標?

例小提琴:http://www.sqlfiddle.com/#!6/d41d8/14320

+0

所以,如果我的理解,這將ouptut,在這個例子中,更多的則14個幾百萬行,對吧? –

+0

@FabienTheSolution實際上,每個記錄的目標是每天1行。因此,在上面的例子中,您將獲得2014年1月1日至2014年1月14日的15天數據。所以如果你有2個客戶,那麼你會得到30個結果。如果你有900萬客戶,那麼你會得到1.35億的結果。 – Kittoes0124

+0

@BogdanSahlean嘿,我真的很抱歉,我認爲我的例子是爲自己說話的。你肯定指引我朝着正確的方向發展,迄今爲止你的建議非常有幫助。我提供了小提琴作爲一種簡單的方式,儘可能接近我的數據,而不需要真正擁有它。 – Kittoes0124

回答

2

SQL Fiddle

MS SQL Server 2012的架構設置

查詢1

SELECT S.CustomerId, S.DateValue, T.Balance 
FROM (
SELECT DISTINCT CustomerId, DateValue 
FROM TestData, Calendar 
WHERE DateValue BETWEEN '1/1/2014' AND '1/14/2014') S 
CROSS APPLY (
SELECT TOP(1) Balance 
FROM TestData B 
WHERE B.StartDate <= S.DateValue AND B.CustomerId = S.CustomerId 
ORDER BY StartDate DESC 
) AS T 
ORDER BY CustomerId, DateValue 

Results

| CUSTOMERID | DATEVALUE | BALANCE | 
|------------|------------|---------| 
|  123 | 2014-01-01 | 25000 | 
|  123 | 2014-01-02 | 25000 | 
|  123 | 2014-01-03 | 25000 | 
|  123 | 2014-01-04 | 25000 | 
|  123 | 2014-01-05 | 25000 | 
|  123 | 2014-01-06 | 25000 | 
|  123 | 2014-01-07 | 20000 | 
|  123 | 2014-01-08 | 20000 | 
|  123 | 2014-01-09 | 10000 | 
|  123 | 2014-01-10 | 10000 | 
|  123 | 2014-01-11 | 10000 | 
|  123 | 2014-01-12 | 10000 | 
|  123 | 2014-01-13 | 10000 | 
|  123 | 2014-01-14 | 10000 | 
|  456 | 2014-01-01 | 25000 | 
|  456 | 2014-01-02 | 25000 | 
|  456 | 2014-01-03 | 25000 | 
|  456 | 2014-01-04 | 25000 | 
|  456 | 2014-01-05 | 25000 | 
|  456 | 2014-01-06 | 25000 | 
|  456 | 2014-01-07 | 20000 | 
|  456 | 2014-01-08 | 20000 | 
|  456 | 2014-01-09 | 10000 | 
|  456 | 2014-01-10 | 10000 | 
|  456 | 2014-01-11 | 10000 | 
|  456 | 2014-01-12 | 10000 | 
|  456 | 2014-01-13 | 10000 | 
|  456 | 2014-01-14 | 10000 | 
+1

與我的第二個查詢基本不一樣嗎? – Kittoes0124

+0

是的......你是對的....我開始玩你的第一個查詢....看起來我已經結束了你的第二個... –

+0

那麼這個呢? –

0

這裏是我結束了去查詢:

SELECT C.DateValue, T.CustomerId, T.Balance 
FROM Calendar C 
CROSS APPLY (
    SELECT B.CustomerId, B.Balance 
    FROM TestData B 
    WHERE C.DateValue >= B.StartDate AND (C.DateValue < B.EndDate OR B.EndDate IS NULL) 
) AS T 
WHERE C.DateValue BETWEEN '1/1/2014' AND '1/14/2014' 
ORDER BY CustomerId, DateValue 

@BogdanSahlean值得很多信貸指着我在正確的方向。關鍵是確保CROSS APPLY中的WHERE子句得到正確調整。

SQL小提琴:http://www.sqlfiddle.com/#!6/d41d8/14376

相關問題