внешнее соединение на том же столе sql - PullRequest
0 голосов
/ 15 июня 2011

Я создаю машину времени с помощью 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.Как я мог построить этот запрос?

Ответы [ 4 ]

2 голосов
/ 15 июня 2011

Хм, я думаю, я понимаю. Вы хотите получить все файлы, которые совпадают с 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 голосов
/ 15 июня 2011

Я изменил его, потому что я работаю с большим количеством файлов, поэтому решение отлично работает, но не для запросов, связанных с большим количеством записей.Вот что я разработал.

давайте предположим, что у меня есть следующие записи:

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 для переменной в моем коде, но это просто для иллюстрации изменений, которые я сделал.

0 голосов
/ 15 июня 2011

Фил Сэндлер х ответ работает. Это тоже:

    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 голосов
/ 15 июня 2011

Я не знаю 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 и включаете либо записи, у которых нет соответствия (они новые), либо где измененные даты не совпадают.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...