簡體   English   中英

將函數從SQL Server轉換為MS Access

[英]Converting a function from SQL Server to MS Access

我有一些代碼用於在表中插入值,用SQL Server編寫:

創建表/構建架構:

  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。

有幾點可以幫助您入門:

IIf存在於Access中,因此無需更改。

Access中不存在CROSS JOIN關鍵字; 在表名/子查詢之間使用逗號( , )來返回笛卡爾積。 您可能還需要將引用笛卡爾積的ON語句移動到WHERE子句中。

如果Access中的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查詢,然后在另一個查詢中將這些部分連接在一起。 分解問題也可以幫助您簡化從SQL Server的過渡。

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

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

我很想知道為什么要將其轉換為訪問VBA。

我將查詢SQL作為VBA中的字符串構建,然后從SQL字符串創建QueryDef對象。

構建SQL字符串時,您會發現答案中概述的技術可以幫助您。

下面的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] 
               )     
    ;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM