我正在MS Access 2010中开发一个数据库。我有两个表,一个用于Deals(tblDeals),另一个用于Deal Items(tblDealItems)。
我需要跟踪这些表中数据的历史记录,因此我在每个表中都使用了DateEffective字段和DateEnd字段。
问题在于,两个表中每个表中的数据可以在不同的日期独立变化,这使得(实际上我不可能)返回记录集,该记录集具有在此期间发生的一系列事件的真实历史记录。这笔交易。
这些表格包含一项特定交易的以下数据:“交易3”:
tblDeals:
DealID DealName AssetClassID DateEffective DateEnd
------ -------- ------------ ------------- -------
3 Deal 3 3 1 Jan 2010 1 Jul 2011
3 Deal 3 2 1 Jul 2011 1 Oct 2011
3 Deal 3 1 1 Oct 2011
tblDealItems:
DealItemID DealID CategoryID ParticipantID Amount DateEffective DateEnd
---------- ------ ---------- ------------- ------ ------------- -------
13 3 3 2 1500 1 Jan 2010 1 Jun 2011
13 3 1 2 1500 1 Jun 2011 6 Jun 2011
13 3 1 2 6000 6 Jun 2011 1 Sep 2011
13 3 3 2 6000 1 Sep 2011
因此,交易的实际历史就是这个(手动创建 - 这个(除了“描述”列 - 这是显而易见的,因此很明显每行中有什么变化)是我想要返回的) :
Date (Description) DealID DealName AssetClassID CategoryID ParticipantID Amount
---------- --------------------- ------ -------- ------------ ---------- ------------- ------
1 Jan 2010 (Deal 3 Created) 3 Deal 3 3 3 2 1500
1 Jun 2011 (Category Changed) 3 Deal 3 3 1 2 1500
6 Jun 2011 (Amount Changed) 3 Deal 3 3 1 2 6000
1 Jul 2011 (Asset Class Changed) 3 Deal 3 2 1 2 6000
1 Sep 2011 (Category Changed) 3 Deal 3 2 3 2 6000
1 Oct 2011 (Asset Class Changed) 3 Deal 3 1 3 2 6000
显然,如果我在共享密钥上加入两个表,我会得到一个包含十二行(3 * 4)的表,而不是描述历史记录的六行。
我知道我需要能够以某种方式将表格加在一起,以便我可以生成交易的真实历史,但我只是不知道如何! (我真的是一个Excel人,而不是SQL人员!)
我想我已经确定了解决上述问题所需的确切内容:
对于qryDates中的每个日期,我需要找到小于或等于该日期的最大tblDeals.DateEffective和小于或等于该日期的最大tblDealItems.DateEffective。
我需要从连接tblDeals和tblDealItems的查询中返回该行,该查询具有这两个确切的日期。
感激不尽的任何帮助。
答案 0 :(得分:2)
我暂时忽略'描述',因为它增加了相当多的复杂性(并且可能更适合报告):
第一
CREATE VIEW qryDates
AS
SELECT DISTINCT T1.DealID,
T1.DateEffective AS tblDeals_DateEffective,
(
SELECT MAX(T2.DateEffective)
FROM tblDealItems AS T2
WHERE T1.DealID = T2.DealID
AND T2.DateEffective <= T1.DateEffective
) AS tblDealItems_DateEffective
FROM tblDeals AS T1;
第二
CREATE VIEW qryDates2
AS
SELECT DISTINCT T2.DealID,
T2.DateEffective AS tblDealItems_DateEffective,
(
SELECT MAX(T1.DateEffective)
FROM tblDeals AS T1
WHERE T1.DealID = T2.DealID
AND T1.DateEffective <= T2.DateEffective
) AS tblDeals_DateEffective
FROM tblDealItems AS T2
然后
SELECT T2.DateEffective AS [Date], '' AS Description,
T1.DealName, T1.AssetClassID,
T2.CategoryID, T2.ParticipantID, T2.Amount
FROM (
tblDeals AS T1
INNER JOIN
qryDates2 AS Q2
ON T1.DateEffective = Q2.tblDeals_DateEffective
AND T1.DealID = Q2.DealID
)
INNER JOIN tblDealItems AS T2
ON T2.DateEffective = Q2.tblDealItems_DateEffective
AND T2.DealID = Q2.DealID
UNION
SELECT T1.DateEffective AS [Date], '' AS Description,
T1.DealName, T1.AssetClassID,
T2.CategoryID, T2.ParticipantID, T2.Amount
FROM (
tblDeals AS T1
INNER JOIN
qryDates AS Q1
ON T1.DateEffective = Q1.tblDeals_DateEffective
AND T1.DealID = Q1.DealID
)
INNER JOIN tblDealItems AS T2
ON T2.DateEffective = Q1.tblDealItems_DateEffective
AND T2.DealID = Q1.DealID;
样本中数据的质量很好:实际上,连接可能需要在外部以补偿不良数据。请注意,您的tblDeals
表未完全标准化(提示:DealName
重复)。
注意:
显然,如果我在共享密钥上加入两个表,我会得到一个表 有十二行(3 * 4)而不是描述六行的六行 历史。
您可以使用UNION
获取每笔交易的唯一活动日期:
SELECT DealID, DateEffective
FROM tblDeals
UNION
SELECT DealID, DateEffective
FROM tblDealItems;
这是一个repro:在temp文件夹中创建一个新的mdb,创建表和视图(注意CREATE VIEW
在Access中工作;),添加测试数据(根据问题)然后执行查询并在消息框中显示结果;不需要引用,只需复制+粘贴到任何VBA模块,例如使用新的Excel工作簿:)
Sub NickNick2()
On Error Resume Next
Kill Environ$("temp") & "\DropMe.mdb"
On Error GoTo 0
Dim cat
Set cat = CreateObject("ADOX.Catalog")
With cat
.Create _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & _
Environ$("temp") & "\DropMe.mdb"
With .ActiveConnection
Dim Sql As String
Sql = "CREATE TABLE tblDeals (DealID INT, DealName VARCHAR(100), AssetClassID INT, DateEffective DATETIME, DateEnd DATETIME);"
.Execute Sql
Sql = "CREATE TABLE tblDealItems (DealItemID INT, DealID INT, CategoryID INT, ParticipantID INT, Amount INT, DateEffective DATETIME, DateEnd DATETIME);"
.Execute Sql
Sql = _
" CREATE VIEW qryDates " & _
" AS " & _
" SELECT DISTINCT T1.DealID, " & _
" T1.DateEffective AS tblDeals_DateEffective, " & _
" ( " & _
" SELECT MAX(T2.DateEffective) " & _
" FROM tblDealItems AS T2 " & _
" WHERE T1.DealID = T2.DealID " & _
" AND T2.DateEffective <= T1.DateEffective " & _
" ) AS tblDealItems_DateEffective " & _
" FROM tblDeals AS T1;"
.Execute Sql
Sql = _
" CREATE VIEW qryDates2 " & _
" AS " & _
" SELECT DISTINCT T2.DealID, " & _
" T2.DateEffective AS tblDealItems_DateEffective, " & _
" ( " & _
" SELECT MAX(T1.DateEffective) " & _
" FROM tblDeals AS T1 " & _
" WHERE T1.DealID = T2.DealID " & _
" AND T1.DateEffective <= T2.DateEffective " & _
" ) AS tblDeals_DateEffective " & _
" FROM tblDealItems AS T2;"
.Execute Sql
Sql = _
"INSERT INTO tblDeals VALUES (3, 'Deal 3', 3, '2010-01-01 00:00:00', '2011-07-01 00:00:00');"
.Execute Sql
Sql = _
"INSERT INTO tblDeals VALUES (3, 'Deal 3', 2, '2011-07-01 00:00:00', '2011-10-01 00:00:00');"
.Execute Sql
Sql = _
"INSERT INTO tblDeals VALUES (3, 'Deal 3', 1, '2011-10-01 00:00:00', NULL);"
.Execute Sql
Sql = _
"INSERT INTO tblDealItems VALUES (13, 3, 3, 2, 1500, '2010-01-01 00:00:00', '2011-06-01 00:00:00');"
.Execute Sql
Sql = _
"INSERT INTO tblDealItems VALUES (13, 3, 1, 2, 1500, '2011-06-01 00:00:00', '2011-06-06 00:00:00');"
.Execute Sql
Sql = _
"INSERT INTO tblDealItems VALUES (13, 3, 1, 2, 6000, '2011-06-06 00:00:00', '2011-09-01 00:00:00');"
.Execute Sql
Sql = _
"INSERT INTO tblDealItems VALUES (13, 3, 3, 2, 6000, '2011-09-01 00:00:00', NULL);"
.Execute Sql
Sql = _
"SELECT T2.DateEffective AS [Date], '' AS Description, " & _
" T1.DealName, T1.AssetClassID, " & _
" T2.CategoryID, T2.ParticipantID, T2.Amount " & _
" FROM ( " & _
" tblDeals AS T1 " & _
" INNER JOIN " & _
" qryDates2 AS Q2 " & _
" ON T1.DateEffective = Q2.tblDeals_DateEffective " & _
" AND T1.DealID = Q2.DealID " & _
" ) " & _
" INNER JOIN tblDealItems AS T2 " & _
" ON T2.DateEffective = Q2.tblDealItems_DateEffective " & _
" AND T2.DealID = Q2.DealID " & _
"UNION " & _
"SELECT T1.DateEffective AS [Date], '' AS Description, " & _
" T1.DealName, T1.AssetClassID, " & _
" T2.CategoryID, T2.ParticipantID, T2.Amount " & _
" FROM ( " & _
" tblDeals AS T1 " & _
" INNER JOIN " & _
" qryDates AS Q1 " & _
" ON T1.DateEffective = Q1.tblDeals_DateEffective " & _
" AND T1.DealID = Q1.DealID " & _
" ) "
Sql = Sql & _
" INNER JOIN tblDealItems AS T2 " & _
" ON T2.DateEffective = Q1.tblDealItems_DateEffective " & _
" AND T2.DealID = Q1.DealID " & _
" ORDER " & _
" BY 1;"
Dim rs
Set rs = .Execute(Sql)
MsgBox rs.GetString
End With
Set .ActiveConnection = Nothing
End With
End Sub