2009-10-20 40 views
1

在使用Access 2007作爲前端和SQL2005作爲後端的數據庫中,存在以下問題。合併具有連續日期的記錄

表AI有以下數據結構

Table A 

ID  Date   Supplier_ID 
1  10/22/2009  1    
2  10/23/2009  1    
3  10/24/2009  2 
4  10/25/2009  2   
5  10/26/2009  1 

我需要合併有連續的日期和同一Supplier_ID值,對於這些連續的記錄增加一個新列(天數),並將其寫入數據到表B中,以便我有

Table B 

ID  Date   Supplier_ID  Days 
1  10/22/2009  1    2 
2  10/24/2009  2    2 
3  10/26/2009  1    1 

只應該合併連續的日子。因此,表A中的ID 5作爲新記錄添加到表B中。自從我開始使用Access VBA以來,已經有一段時間了,並且想知道正確的方法是什麼。

+0

你能否澄清你的例子? (1)是否有可能在同一日期擁有多個Supplier_ID,以及(2)如果Table_B中的數據是以日期訂單或Supplier_ID訂單編寫的,那麼這很重要嗎? – heferav 2009-10-20 12:41:37

+0

澄清 無法在同一日期擁有多個Supplier_ID,並且無論數據插入到表B中的順序如何。 – Istari 2009-10-20 13:03:47

+0

您需要添加更多信息。這些日子是連續的嗎?即將永遠是22,23,24,25?或者有可能會跳過?例如22,24,25 – 2009-10-20 21:33:17

回答

1

你有很多的業務規則有一些獨特的假設。如表A是從來沒有空,表B總是空運行此

之前無論如何,下面的代碼將工作使用的樣本數據:

Dim rs As Recordset 
Dim dbs As Database, qdf As QueryDef, strSQL As String 
Set dbs = CurrentDb 

Dim Supplier_ID As Integer 
Dim Days As Integer 
Dim FirstDate As Date 
Set qdf = dbs.CreateQueryDef("", "select [Date], Supplier_ID from tableA order by [date] ") 
Set rs = qdf.OpenRecordset() 

Supplier_ID = rs!Supplier_ID 
FirstDate = rs!Date 
While Not rs.EOF 
    If rs!Supplier_ID <> Supplier_ID Then 
     If Supplier_ID <> 0 Then 
      ' we don't want to insert the first time we run through this, so we check if Supplier_ID is not zero 
      dbs.Execute ("insert into tableB ([Date], Supplier_ID, Days) select #" + Format(FirstDate, "dd-mmm-yyyy") + "#, " + Str(Supplier_ID) + ", " + Str(Days)) 
      Supplier_ID = rs!Supplier_ID 
      FirstDate = rs!Date 
      Days = 0 
     End If 

    End If 
    Days = Days + 1 
    rs.MoveNext 
Wend 

dbs.Execute ("insert into tableB ([Date], Supplier_ID, Days) select #" + Format(FirstDate, "dd-mmm-yyyy") + "#, " + Str(Supplier_ID) + ", " + Str(Days)) 

雖然你可以做到這一點,訪問(一般SQL)ISN對於逐行比較來說,這是最好的選擇。儘管您可以使用cursors或上面的示例代碼,但維護可能是一項挑戰!

1

我不認爲這可以在一個SQL中完成,因此您必須編寫一些代碼。我的第一個想法是製作某種字典(Key = SupplierID,Value =(FirstDate,LastDate)),並使用迭代遍歷表A中的數據並填充字典的算法,類似於此(僞代碼) :

records = recordset: SELECT * FROM Table A ORDER BY Date 
Do Until records.EOF 
    If dictionary contains records!SupplierID 
     If dictionaryEntry.LastDate = records!Date - 1 
      dictionaryEntry.LastDate = records!Date 
     Else 
      Make Table B Entry (Days = LastDate - FirstDate) and remove dictionary entry 
     End If 
    Else 
     Create dictionary entry for this Supplier with LastDate = FirstDate = records!Date 
    End If 

    records.MoveNext 
Loop 
records.Close 

Make Table B Entries for all remaining entries in the dictionary 

對於字典,可以使用Scripting.Dictionary,其值爲2元素數組。

2

下面是一些ANSI-92 Query Mode語法SQL DDL和DML重建表和一個可能的解決方案:

CREATE TABLE TableA 
(
ID INTEGER NOT NULL UNIQUE, 
[Date] DATETIME NOT NULL, 
Supplier_ID INTEGER NOT NULL 
); 

INSERT INTO TableA (ID, [Date], Supplier_ID) 
SELECT DT1.ID, DT1.[Date], DT1.Supplier_ID 
FROM (
     SELECT DISTINCT 1 AS ID, '2009-10-22 00:00:00' AS [Date], 1 AS Supplier_ID FROM Customers 
     UNION ALL 
     SELECT DISTINCT 2, '2009-10-23 00:00:00', 1 FROM Customers   
     UNION ALL 
     SELECT DISTINCT 3, '2009-10-24 00:00:00', 2 FROM Customers 
     UNION ALL 
     SELECT DISTINCT 4, '2009-10-25 00:00:00', 2 FROM Customers   
     UNION ALL 
     SELECT DISTINCT 5, '2009-10-26 00:00:00', 1 FROM Customers 
    ) AS DT1; 

CREATE VIEW TableA_StartDates (Supplier_ID, start_date) 
AS 
SELECT T1.Supplier_ID, T1.[Date] 
    FROM TableA AS T1 
WHERE NOT EXISTS (
        SELECT * 
        FROM TableA AS T2 
        WHERE T2.Supplier_ID = T1.Supplier_ID 
          AND DATEADD('D', -1, T1.[Date]) = T2.[Date] 
       ); 

CREATE VIEW TableA_EndDates (Supplier_ID, end_date) 
AS 
SELECT T3.Supplier_ID, T3.[Date] 
    FROM TableA AS T3 
WHERE NOT EXISTS (
        SELECT * 
        FROM TableA AS T4 
        WHERE T4.Supplier_ID = T3.Supplier_ID 
          AND DATEADD('D', 1, T3.[Date]) = T4.[Date] 
       ); 

CREATE VIEW TableA_Periods (Supplier_ID, start_date, end_date) 
AS 
SELECT DISTINCT T5.Supplier_ID, 
     (
     SELECT MAX(S1.start_date) 
      FROM TableA_StartDates AS S1 
     WHERE S1.Supplier_ID = T5.Supplier_ID 
       AND S1.start_date <= T5.[Date] 
     ), 
     (
     SELECT MIN(E1.end_date) 
      FROM TableA_EndDates AS E1 
     WHERE E1.Supplier_ID = T5.Supplier_ID 
       AND T5.[Date] <= E1.end_date 
     )   
    FROM TableA AS T5; 

SELECT P1.Supplier_ID, P1.start_date, P1.end_date, 
     DATEDIFF('D', P1.start_date, P1.end_date) + 1 AS Days 
    FROM TableA_Periods AS P1;