2015-09-28 49 views
1

我有一些代碼設計在表中插入值,寫在SQL Server:轉換從SQL Server的功能到MS Access

創建表/建模式:

CREATE TABLE Inter 
    ([id] int, [MarkDate] date, [MaturityDate] date, [ZeroRate] int) 
; 

INSERT INTO Inter 
    ([id], [MarkDate], [MaturityDate], [ZeroRate]) 

VALUES 
    (1, '2015-07-02', '2015-07-02', 1), 
    (2, '2015-07-02', '2015-07-03', 5), 
    (3, '2015-07-02', '2015-07-06', 15) 
; 


CREATE TABLE allDates 
    ([id] int, [MaturityDate] date) 
; 

INSERT INTO allDates 
    ([id], [MaturityDate]) 

VALUES 
    (1, '2015-07-01'), 
    (2, '2015-07-02'), 
    (3, '2015-07-03'), 
    (4, '2015-07-04'), 
    (5, '2015-07-05'), 
    (6, '2015-07-06'), 
    (7, '2015-07-07'), 
    (8, '2015-07-08'), 
    (9, '2015-07-09') 
; 

CREATE TABLE rangesInter 
    ([id] int, [MarkDate] date, [begindate] date, [enddate] date, startRate float, rateChange float); 


INSERT INTO rangesInter 
    SELECT 
     I1.id, 
     I1.[MarkDate], 
     I1.[MaturityDate] begindate, 
     I2.[MaturityDate] enddate, 
     I1.[ZeroRate] startRate, 
     (I2.ZeroRate - I1.ZeroRate) * 1.0/DATEDIFF (day , I1.[MaturityDate], I2.[MaturityDate]) rateChange   
    FROM Inter I1 
    inner join Inter I2 
    on I1.id = I2.id - 1; 

插入值:

SELECT 
    IIF(i.MarkDate IS NULL, r.MarkDate, i.MarkDate) as MarkDate, 
    a.MaturityDate, 
    IIF(i.ZeroRate IS NULL, 
      r.startRate + DATEDIFF (day , r.begindate, a.MaturityDate) * rateChange, 
      i.ZeroRate) as ZeroRate, 
    i.*, r.* 
FROM 
    allDates a 
LEFT JOIN 
    Inter I ON a.MaturityDate = I.MaturityDate 
CROSS JOIN 
    (SELECT 
     MIN(MaturityDate) minDate, MAX(MaturityDate) maxDate 
    FROM Inter) AS t 
LEFT JOIN 
    (SELECT 
     I1.id, I1.[MarkDate], 
     I1.[MaturityDate] begindate, I2.[MaturityDate] enddate, 
     I1.[ZeroRate] startRate, 
     (I2.ZeroRate - I1.ZeroRate) * 1.0/DATEDIFF (day , I1.[MaturityDate], I2.[MaturityDate]) rateChange   
    FROM 
     Inter I1 
    INNER JOIN 
     Inter I2 ON I1.id = I2.id - 1) r ON a.MaturityDate > r.[begindate] 
              AND a.MaturityDate < r.[enddate] 
WHERE 
    a.MaturityDate >= t.minDate 
    AND a.MaturityDate <= t.maxDate; 

我怎麼會去這個代碼轉換到MS Access VBA?

我不知道如何開始轉換代碼的「插入值」部分與Access VBA工作。

+0

看起來合法的給我。你真的嘗試在Access中運行該代碼嗎?它給了你什麼具體的錯誤?如果有的話,我會認爲它不會反過來工作;我以爲你需要在SQL Server中使用CASE WHEN語句而不是IIF。 –

+0

在VBA中編寫代碼時,您會發現此答案中概述的技術可幫助您簡化和在VBA中構建的SQL字符串請參閱:http://stackoverflow.com/questions/31684546/how-to-format-a-sql-string這是一個可讀的代碼塊,它的格式很好 – HarveyFrench

回答

1

我很想知道爲什麼要轉換這是在訪問VBA。

我將建立查詢SQL作爲VBA字符串,然後創建一個從SQL字符串QueryDef對象。

在構建SQL字符串時,您會發現this回答可幫助您。

一些更實際點顯示在下面的SQL:

在你的代碼中刪除笛卡兒連接,明確如下。

所有列的別名和表的別名需要一個 「AS」

相反IIF的,你可以使用

nz(MyFieldWithNulls, AnotherfieldToBeUsedWhenItisNull) 

更換DATEDIFF如圖

SELECT Nz(i.MarkDate, r.MarkDate) as MarkDate 
    , a.MaturityDate 
    , Nz(i.ZeroRate 
     , r.startRate + Cint(a.MaturityDate - r.begindate) * rateChange 
     ) as ZeroRate 
    , i.* 
    , r.* 
FROM ( (SELECT allDates.* 
      FROM allDates 
       INNER JOIN (SELECT MIN(MaturityDate) AS minDate 
            , MAX(MaturityDate) AS maxDate 
           FROM Inter 
          ) AS Inter 
         ON (allDates.MaturityDate >= Inter.minDate 
           AND 
           allDates.MaturityDate <= Inter.maxDate 
          ) 
     ) AS a 
     LEFT JOIN Inter AS I 
       ON a.MaturityDate = I.MaturityDate 
    ) 
    LEFT JOIN (SELECT , I1.id 
         , I1.[MarkDate] 
         , I1.[MaturityDate] AS begindate 
         , I2.[MaturityDate] AS enddate, 
         , I1.[ZeroRate]  AS startRate, 
         , (I2.ZeroRate - I1.ZeroRate) * 1.0 
         /DATEDIFF (day , I1.[MaturityDate], I2.[MaturityDate]) 
          AS rateChange   
        FROM Inter I1 
         INNER JOIN Inter I2 
           ON I1.id = (I2.id - 1) 
       ) AS r 
      ON (a.MaturityDate > r.[begindate] 
       AND 
       a.MaturityDate < r.[enddate] 
       )  
    ; 
+0

感謝您的回覆。因爲IIF已經存在於MS訪問中,所以使用「nz」而不是IIF的優點是什麼? – beeba

+0

這是一個更簡單的語法,它可以減少輸入。我懷疑它也可能更快。 – HarveyFrench

+0

我使用了鏈接到的「aa」過程來構建SQL字符串,但是我需要做什麼來創建相關的QueryDef對象 - 我正在試圖遵循[this](https://msdn.microsoft.com /en-us/library/bb177500(v=office.12).aspx)但不知道如何繼續。 – beeba

2

有幾點讓你開始:

IIf存在於訪問了,所以沒有必要改變這種狀況。

CROSS JOIN關鍵字訪問不存在;在表名/子查詢之間使用逗號(,)來返回笛卡爾積。您可能還需要您ON聲明指的是笛卡爾乘積移動到WHERE條款。

當你在訪問一個ON條款多個項目,他們需要用括號包圍。例如:

... ON (f1.ID = f2.ID AND f1.Name = f3.Name) ... 

另外,當您在Access SQL語句中連接多個表時,每個表都必須用圓括號包圍。例如: -

SELECT ... 
FROM 
    ((Table1 t1 
     INNER JOIN Table2 t2 ON t1.ID = t2.ID) 
     INNER JOIN Table3 t3 ON t1.ID = t3.ID) 
     INNER JOIN Table4 t4 ON t1.ID = t4.ID 

混合一起在一個單一的查詢類型時,您可能會收到錯誤(如笛卡爾,左內)。如果是這樣,我建議將查詢分解成幾個Access查詢,每個Access查詢都有相似的連接類型,然後在另一個查詢中將這些部分連接在一起。分解這個問題也可以幫助您簡化從SQL Server的轉換。

訪問也有類似於SQL Server的一個DateDiff功能。但是,第一個參數是表示間隔的字符串(例如,day =「d」,month =「m」等)。所以,你可以像這樣替換你DATEDIFF功能:

DateDiff("d", I1.[MaturityDate], I2.[MaturityDate]) 
+0

感謝您的回覆。你有什麼建議如何重新創建表的代碼的第一部分? 「CREATE TABLE」應該在Access中工作,所以我原以爲我不需要更改代碼,但它似乎不工作。 – beeba

+0

您的CREATE TABLE語句適用於我,但請記住,在Access中,每個查詢只能執行一條語句。嘗試將'CREATE TABLE ...;'放在它自己的查詢中。 INSERT必須在單獨的查詢中。另外,在Access中,您不能一次使用多個'VALUES'作爲'INSERT'語句。每條語句只能插入一行。處理這種限制的一種方法是創建一個VBA語句來執行所有的插入操作。 – transistor1

+0

另一個建議 - 我想要做的是編號我的訪問查詢(例如「01創建表」,「02插入數據到表」,等等......)然後你可以運行一個VBA方法來運行所有的查詢一次,例如[this one](http://fieldeffect.info/wp/frontpage/vba_library/#Run_Numbered_Queries_in_an_Access_Database)。 – transistor1