![](/img/trans.png)
[英]Converting multiple IIfs when converting from MS Access to SQL Server
[英]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.