繁体   English   中英

同一张表上的外连接 sql

[英]outer join on same table sql

我正在用 c# 创建一个时间机器。 时间机器是一种创建文件备份的方式,我可以访问特定文件,就像在特定时间一样。 无论如何,我这样做的方式是查找目录中的所有文件,并将这些文件信息存储在名为 table1 的表中。 因此,如果我第一次扫描我的计算机,假设我只有 3 个文件,因此我的表看起来像:

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 已修改并且文件 Z 已创建。 我不想获取文件 A,因为该文件已经存在相同的 DateModified。 我怎么能建立那个查询?

嗯,我想我明白了。 您想获取与 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

我不知道 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 作为变量,但这只是为了说明我所做的更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM