同一sql表上的外部联接
我正在用c创建一个时间机器。时间机器是一种创建文件备份的方法,我可以像在特定时间一样访问特定文件。无论如何,我这样做的方式是查找目录中的所有文件,并将这些文件信息存储在名为table1的表中。因此,如果我第一次扫描我的计算机,让我们假设我只有3个文件,因此我的表看起来像:同一sql表上的外部联接,sql,sqlite,Sql,Sqlite,我正在用c创建一个时间机器。时间机器是一种创建文件备份的方法,我可以像在特定时间一样访问特定文件。无论如何,我这样做的方式是查找目录中的所有文件,并将这些文件信息存储在名为table1的表中。因此,如果我第一次扫描我的计算机,让我们假设我只有3个文件,因此我的表看起来像: ID FullName DateModified DateInsertedToDatabase 1 C:\A 456588731 0 2 C:\B
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
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
现在我想复制文件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
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被修改,文件Z被创建。我不想获取文件,因为该文件已存在,并且具有相同的修改日期。我怎样才能建立那个查询?嗯,我想我明白了。是否要获取与MAXDateInsertedToDatabase匹配的所有文件,但前一行中没有与其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
我不知道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,并包括不匹配的记录(它们是新的)或修改日期不匹配的记录 的作品。这也是:
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
我修改了它,因为我正在处理大量文件,因此该解决方案非常有效,但不适用于处理大量记录的查询。以下是我的计算结果 假设到目前为止我有以下记录:
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)
)
这就返回了:
这个查询的执行速度要快得多。显然,我必须在代码中更改变量的4,但这只是为了说明我所做的更改 +1 tablename在SQLite中是一个语法错误,但一般技术是可靠的。