具有有效日期的两个表,其中数据可以独立地变化

时间:2011-09-24 13:26:06

标签: sql ms-access

我正在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的查询中返回该行,该查询具有这两个确切的日期。

感激不尽的任何帮助。

1 个答案:

答案 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