2016-01-13 94 views
1

使用SQL Server 2012中我有一個名爲AllbucketSQL插入丟失的日期

CustodianAccountNum symbol EndDate ManagerName MarketValue NetReturn 
A9G040819 wabix 12/31/2013 GMO Benchmark 34751.10987 0.004072 
A9G040819 wabix 1/31/2014 GMO Benchmark 34128.88767 -0.017905 
A9G040819 wabix 2/28/2014 GMO Benchmark 49969.8081 0.0202 
A9G040819 wabix 3/31/2014 GMO Benchmark 50370.993 0.008028 
A9G040819 wabix 4/30/2014 GMO Benchmark 50995.0584 0.
A9G040819 amj 12/31/2013 JPMorgan Alerian 1234.55 -0.008154 
A9G040819 amj 2/28/2014 JPMorgan Alerian 14849.76 -0.018599 
A9G040819 amj 3/31/2014 JPMorgan Alerian 14892.8 0.015203 
A9G040819 amj 4/30/2014 JPMorgan Alerian 15513.6 0.041684 

我試圖從一個系統加載該數據到另一個表。但是,它要求每個給定的CustodianAccountNum,因爲所有符號在它們都存在的時間段內具有相同的日期間隔。

請注意,amj缺少1/31/2014。線索是至少有一個其他安全性,在這種情況下,wabix在同一時間段內具有該日期。另外請注意,有時日期是月內的,例如1/15/2014

我曾希望做一些類似於自我加入和分區的操作,我爲給定的CustodianAccountNum採取所有可能的不同日期,然後強制所有行在期間具有相同的週期性它們重疊的時間跨度。對於那些不是原始的並從該時間段內存在的另一個符號'借來的'的插值行,我想從該符號的前一行拉動LAG市場價值(如果前一行不存在,則存在0)並強制所有其他值爲零。原始數據中還有其他列,但我試圖保持這個例子簡單。

因此,理想的情況是AMJ應該是這樣的,因爲wabix有2014年1月31日日

CustodianAccountNum symbol EndDate ManagerName MarketValue NetReturn 
    A9G040819 amj 12/31/2013 JPMorgan Alerian 1234.55 -0.008154 
A9G040819  amj 1/31/2014 JPMorgan Alerian 1234.55 -0.0 
    A9G040819 amj 2/28/2014 JPMorgan Alerian 14849.76 -0.018599 
    A9G040819 amj 3/31/2014 JPMorgan Alerian 14892.8 0.015203 
    A9G040819 amj 4/30/2014 JPMorgan Alerian 15513.6 0.041684 

失蹤日期的指導原則是,如果任何其他符號具有由給定custodianaccountnum paritioned的日期。有數千個不同的accountnums,但他們只需要按給定accountnum對齊

我的問題是隻有在每個帳戶符號的生命週期中的日期差距。如果在數年前存在另一個符號名稱,我不需要添加很多個月。我只需要它們在所有符號中的給定符號的第一個到最後一個日期之間同步,這些符號在時間上重疊。

UPDATE

戈登·利諾夫的回答讓我接近,但不能令人信服。我不得不將外部應用更改爲交叉應用,或者我在所有列中獲得了成千上萬的空記錄。

我修改了查詢以顯示所有需要的列,但是這個查詢導致所有的市場價值都爲0.基本上我想強制所有值爲0的派生行(1/31/2014在我的例子中)除了市場價格,我想從以前的市場價值拉動。但是,對於所有非派生行,我希望在整行中使用原始值。

select 

ab.drank,d.EndDate,ab.BranchName,ab.EntityID,ab.CustodianAccountNum,ab.AccountID,ab.ManagerName, 
ab.FTAssetStyle,ab.FTAssetClass,ab.PWMSecurityID,ab.AssetClassCode,ab.AssetClass,ab.Symbol,ab.SecType, 
ab.Cusip,ab.Held,ab.MarketValue, 
0 AS GrossFlow,0 AS GrossWeight,0 AS GrossReturn,0 AS NetFlow,0 AS NetWeight, 
0 AS NetReturn,0 AS PortfolioFees,0 AS PortfolioExpenses,0 AS ManagerFees,0 AS Income 

from (select distinct CustodianAccountNum, enddate from Allbucket) d join 
    (select distinct CustodianAccountNum, symbol from Allbucket) s 
    on d.CustodianAccountNum = s.CustodianAccountNum CROSS apply 
    (select top 1 ab.* 
    from Allbucket ab 
    where d.CustodianAccountNum = ab.CustodianAccountNum and 
     d.enddate <= ab.enddate and 
     s.symbol = ab.symbol 
      AND ab.CustodianAccountNum = 'A9G040819' 
    order by d.enddate desc 
    ) ab 
+0

那麼,什麼都有你試過了嗎? – dfundako

+0

在這種情況下,你想'wabix'和'amj'具有相同的日期嗎?如果有兩個以上的帳戶呢?你想要所有那些具有相同的範圍? –

回答

0

方式略有不同,但依然採用了笛卡爾生產和應用運算符(OUTER APPLY需要在這一個)。如果你不想要前面的值,那麼只需修改COALESCE()。

SQL Fiddle

的MS SQL Server 2014架構設置

CREATE TABLE Allbucket 
    ([CustodianAccountNum] varchar(9), [symbol] varchar(5), [EndDate] datetime, [ManagerName] varchar(16), [MarketValue] numeric 
    , [NetReturn] decimal(12,6)) 
; 

INSERT INTO Allbucket 
    ([CustodianAccountNum], [symbol], [EndDate], [ManagerName], [MarketValue], [NetReturn]) 
VALUES 
    ('A9G040819', 'wabix', '2013-12-31 00:00:00', 'GMO Benchmark', 34751.10987, 0.004072), 
    ('A9G040819', 'wabix', '2014-01-31 00:00:00', 'GMO Benchmark', 34128.88767, -0.017905), 
    ('A9G040819', 'wabix', '2014-02-28 00:00:00', 'GMO Benchmark', 49969.8081, 0.0202), 
    ('A9G040819', 'wabix', '2014-03-31 00:00:00', 'GMO Benchmark', 50370.993, 0.008028), 
    ('A9G040819', 'wabix', '2014-04-30 00:00:00', 'GMO Benchmark', 50995.0584, 0.), 
    ('A9G040819', 'amj', '2013-12-31 00:00:00', 'JPMorgan Alerian', 1234.55, -0.008154), 
    ('A9G040819', 'amj', '2014-02-28 00:00:00', 'JPMorgan Alerian', 14849.76, -0.018599), 
    ('A9G040819', 'amj', '2014-03-31 00:00:00', 'JPMorgan Alerian', 14892.8, 0.015203), 
    ('A9G040819', 'amj', '2014-04-30 00:00:00', 'JPMorgan Alerian', 15513.6, 0.041684) 
; 

查詢1

SELECT 
     s.CustodianAccountNum 
    , s.symbol 
    , d.enddate 
    , COALESCE(ab.ManagerName, ap.ManagerName) AS ManagerName 
    , COALESCE(ab.MarketValue, ap.MarketValue) AS MarketValue 
    , COALESCE(ab.NetReturn, 0) AS NetReturn 
FROM (
     SELECT 
      CustodianAccountNum 
      , symbol 
      , MIN(enddate) symstart 
      , MAX(enddate) symend 
     FROM Allbucket 
     GROUP BY 
      CustodianAccountNum 
      , symbol 
    ) s 
     JOIN (
      SELECT DISTINCT 
        cast(enddate as date) as enddate 
      FROM Allbucket 
    ) d ON d.enddate BETWEEN s.symstart AND s.symend 
     LEFT JOIN Allbucket ab ON s.CustodianAccountNum = ab.CustodianAccountNum 
        AND s.symbol = ab.symbol 
        AND ab.enddate = d.enddate 
     OUTER APPLY (
      SELECT TOP 1 
        t.* 
      FROM Allbucket t 
      WHERE s.CustodianAccountNum = t.CustodianAccountNum 
        AND s.symbol = t.symbol 
        AND d.enddate <= t.enddate 
      ORDER BY 
        d.enddate DESC 
    ) ap 

Results

| CustodianAccountNum | symbol | enddate |  ManagerName | MarketValue | NetReturn | 
|---------------------|--------|------------|------------------|-------------|-----------| 
|   A9G040819 | amj | 2013-12-31 | JPMorgan Alerian |  1235 | -0.008154 | 
|   A9G040819 | amj | 2014-01-31 | JPMorgan Alerian |  14850 |   0 | 
|   A9G040819 | amj | 2014-02-28 | JPMorgan Alerian |  14850 | -0.018599 | 
|   A9G040819 | amj | 2014-03-31 | JPMorgan Alerian |  14893 | 0.015203 | 
|   A9G040819 | amj | 2014-04-30 | JPMorgan Alerian |  15514 | 0.041684 | 
|   A9G040819 | wabix | 2013-12-31 | GMO Benchmark |  34751 | 0.004072 | 
|   A9G040819 | wabix | 2014-01-31 | GMO Benchmark |  34129 | -0.017905 | 
|   A9G040819 | wabix | 2014-02-28 | GMO Benchmark |  49970 | 0.0202 | 
|   A9G040819 | wabix | 2014-03-31 | GMO Benchmark |  50371 | 0.008028 | 
|   A9G040819 | wabix | 2014-04-30 | GMO Benchmark |  50995 | 0.| 

注意:您可以使用ISNULL(),而不是COALESCE()

[EDITS]對NetValue數據類型,&變化對結束日期迄今取得校正但這是可選

0

您可以基本上使用cross join生成行。在這種情況下,它實際上是對不同日期和符號的加入,但它仍然是一個笛卡兒積。

然後,CustodianAccountNum,symbolEndDate的組合的最新記錄可以使用outer apply來選擇。

以下是一個細微的變化。這使用left join來引入匹配記錄,然後在不匹配時使用來自兩條記錄的信息。我不知道哪些列應爲0,但這個想法是:

select ab.CustodianAccountNum, ab.symbol, d.EndDate, ab.ManagerName, 
     ab.MarketValue, 0 as NetReturn, 
     ab.xxx,      -- for columns that come from the current row 
     coalesce(ab.yyy, abprev.yyy) -- for columns from the previous row 
from (select distinct CustodianAccountNum, enddate from Allbucket) d join 
    (select distinct CustodianAccountNum, symbol from Allbucket) s 
    on d.CustodianAccountNum = s.CustodianAccountNum left join 
    Allbucket ab 
    on d.CustodianAccountNum = ab.CustodianAccountNum and 
     d.enddate <= ab.enddate and 
     s.symbol = ab.symbol outer apply 
    (seleect top 1 ab.* 
     from Allbucket ab 
     where d.CustodianAccountNum = ab.CustodianAccountNum and 
      d.enddate < ab.enddate and 
      s.symbol = ab.symbol 
     order by d.enddate desc 
    ) abprev 
+0

這幾乎可以工作,但不完全。請在我的原始問題中查看我的更新。 –