2011-06-15 46 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,但这只是为了说明我所做的更改。