2011-06-15 40 views
0

我正在用c#創建一個時間機器。時間機器是一種創建我的文件備份的方式,可以像我在特定時間訪問特定文件一樣。無論如何,我這樣做的方式是通過查找目錄中的所有文件,並將這些文件信息存儲在名爲table1的表中。所以,如果我第一次掃描我的電腦讓我們假設我只有3個文件,所以我的表看起來像:同一張表上的外部連接sql

ID FullName DateModified DateInsertedToDatabase 
1  C:\A  456588731    0 
2  C:\B  955588762    0 
3  C:\C  854587783    0 

可以說,下一次我執行備份我有同樣的3個文件,但我有創建一個新的文件,並修改文件C.其結果是我的表,現在應該是這樣的:

ID FullName DateModified DateInsertedToDatabase 
    1  C:\A  456588731    0 
    2  C:\B  955588762    0 
    3  C:\C  854587783    0 
    4  C:\A  456588731    1 
    5  C:\B  955588762    1 
    6  C:\C  111122212    1 
    7  C:\X  123212321    1 

現在我會想文件C和文件X複製,因爲這些是已更改或創建的文件。我怎樣才能建立一個查詢,我可以獲得文件X和文件C?換句話說,我想所有有DateInsertedToDatabase = 1,該文件不匹配文件,其中DateInsertedToDatabase小於1

如果我沒有說清楚這是我的例子的延續: 讓說我繼續我的榜樣,我刪除文件:B和C,我修改文件X,我創建一個新的文件Z.我的表應該是這樣的:

ID FullName DateModified DateInsertedToDatabase 
    1  C:\A  456588731    0 
    2  C:\B  955588762    0 
    3  C:\C  854587783    0 
    4  C:\A  456588731    1 
    5  C:\B  955588762    1 
    6  C:\C  111122212    1 
    7  C:\X  123212321    1 
    8  C:\A  456588731    2 
    9  C:\X  898989898    2 
    10 C:\Z  789564545    2 

在這裏我會想獲取文件X和Z因爲文件X被修改並且File Z被創建。我不想獲取文件A,因爲該文件已經存在相同的DateModified。我如何構建該查詢?

回答

2

嗯,我想我明白了。您希望獲得與MAX(DateInsertedToDatabase)匹配的所有文件,但沒有與其DateModified匹配的前一行?

你想做我稱之爲「反向內連接」。基本上是一個左連接,它可以過濾掉任何在內連接中成功匹配的東西。還有其他方法可以完成(例如使用子查詢)。

這是在T-SQL:

CREATE TABLE #mytemp 
(
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [FullName] [nvarchar](50) NOT NULL, 
    DateModified [nvarchar](9) NOT NULL, 
    DateInsertedToDatabase [int] NOT NULL 
) 

INSERT INTO #mytemp VALUES ('C:\A', '456588731', '0') 
INSERT INTO #mytemp VALUES ('C:\B', '955588762', '0') 
INSERT INTO #mytemp VALUES ('C:\C', '854587783', '0') 

INSERT INTO #mytemp VALUES ('C:\A', '456588731', '1') 
INSERT INTO #mytemp VALUES ('C:\B', '955588762', '1') 
INSERT INTO #mytemp VALUES ('C:\C', '111122212', '1') 
INSERT INTO #mytemp VALUES ('C:\X', '123212321', '1') 

INSERT INTO #mytemp VALUES ('C:\A', '456588731', '2') 
INSERT INTO #mytemp VALUES ('C:\X', '898989898', '2') 
INSERT INTO #mytemp VALUES ('C:\Z', '789564545', '2') 

SELECT 
    temp1.* 
FROM 
    #mytemp temp1 
    LEFT JOIN #mytemp temp2 ON 
      temp1.ID != temp2.ID --don't match on the same two rows 
      AND temp1.FullName = temp2.FullName --match based on full name 
      AND temp1.DateModified = temp2.DateModified --and date modified 
WHERE 
    temp1.DateInsertedToDatabase = (SELECT MAX(DateInsertedToDatabase) FROM #mytemp) 
    AND temp2.ID IS NULL --filter out rows that would have matched on an INNER JOIN 

DROP TABLE #mytemp 
+0

+1 #tablename是SQLite中的一個語法錯誤,但通用技術是健全的。 – pilcrow 2011-06-15 03:39:56

0

我不知道SqlLite,但我希望這無論如何都會正常工作。它沒有使用任何幻想。

Select t1.* 
From Table1 t1 
Left join Table1 t2 
On t1.FullName = t2.FullName 
And t1.DateInsertedToDatabase = t2.DateInsertedToDatabase + 1 
Where t1.DateInsertedToDatabase = (select max(DateInsertedToDatabase) from Table1) 
And (t1.DateModified <> t2.DateModified or t2.FullName is null) 

加入DateInsertedToDatabase + 1將加入前一個記錄。然後,篩選最高的DateInsertedToDatabase幷包含沒有匹配的記錄(它們是新的)或修改日期不匹配的記錄。

0

Phil Sandleranswer的作品。這個呢,太:

SELECT FullName 
     FROM table1 
INNER JOIN (SELECT FullName, DateModified 
       FROM table1 
      WHERE DateInsertedToDatabase = (SELECT MAX(DateInsertedToDatabase) FROM table1)) d 
    USING (FullName, DateModified) 
    GROUP BY FullName 
    HAVING COUNT(1) = 1 
0

我修改了它,因爲我有很多文件的工作,因此該解決方案的偉大工程,但不適合處理大量的記錄的查詢。這是我制定的。

讓我們假設我到目前爲止這個記錄:

enter image description here

Select * from table1 WHERE DateInserted = 4 
and Path not in(
     select Path from table1 t1 
     where 
      DateInserted = 4 AND 
      Path IN (Select Path from table1 where DateInserted<4) AND 
      DateModified IN (Select DateModified from table1 where DateInserted<4) 
    ) 

和回報:

enter image description here

此查詢工作得更快。我顯然必須在代碼中更改變量4,但這只是爲了說明我所做的更改。