2015-07-23 2 views
2

Поскольку новые записи добавляются в таблицу, мне нужно отметить старые записи для этого уровня, как старые. Я могу сделать это с помощью NOT IN, но NOT EXISTS не работает. Я подозреваю, что это связано с корреляцией подзапросов, как описано здесь: NOT EXISTS query doesn't work on Informix while same query with NOT IN works , но я не понимаю, почему & может использовать дополнительные пояснения. Вот пример кода:T-SQL NOT IN работает, но NOT EXISTS не

CREATE TABLE t2 (id INT, level INT, someDate datetime, mostRecent int) 
GO 
INSERT INTO t2 
SELECT 1, 1, '1/1/2010', 1 UNION ALL 
SELECT 2, 1, '2/2/2010', 1 UNION ALL 
SELECT 3, 2, '3/3/2010', 1 UNION ALL 
SELECT 4, 3, '4/4/2010', 1 UNION ALL 
SELECT 5, 3, '5/5/2010', 1 UNION ALL 
SELECT 6, 3, '6/6/2010', 1 UNION ALL 
SELECT 7, 4, '7/7/2010', 1 UNION ALL 
SELECT 8, 5, '8/8/2010', 1 UNION ALL 
SELECT 9, 6, '9/9/2010', 1 UNION ALL 
SELECT 10, 6, '10/10/2010', 1 UNION ALL 
SELECT 11, 8, '11/11/2012', 1 
GO 
-- this doesn't work 
UPDATE t2 SET mostRecent = 0 
FROM t2 
WHERE NOT EXISTS 
    (SELECT * FROM t2 
    JOIN 
     (SELECT level, max(someDate) as someDate FROM t2 group by level) as maxrows 
    ON t2.someDate = maxrows.someDate) 
GO 
-- this works 
UPDATE t2 SET mostRecent = 0 
FROM t2 
WHERE id NOT IN 
    (SELECT t2.id FROM t2 
    JOIN 
     (SELECT level, max(someDate) as someDate FROM t2 group by level) as maxrows 
    ON t2.someDate = maxrows.someDate) 
+0

Похоже некорректного обновления для меня. Если у вас были SELECT 2, 1, '' 4/4/2010 '', 1 UNION ALL, тогда он нашел бы ID 4 также – Paparazzi

ответ

2

Ваш запрос неправильно, он должен быть:

UPDATE T SET mostRecent = 0 
FROM t2 as T 
WHERE NOT EXISTS 
    (SELECT * FROM 
    (SELECT level, max(someDate) as someDate FROM t2 group by level) as maxrows 
     WHERE T.someDate = maxrows.someDate) 

Я добавил псевдоним для таблицы, чтобы держать его ясно

В исходном запросе, вы не связываете ничего с запросом NOT EXISTS на свой оператор UPDATE, поэтому он всегда будет возвращать результаты, и он будет «существовать» для каждой записи в обновляемой таблице.

+0

Спасибо! Я подозревал, что подзапрос неправильно коррелирует с обновлением. –

3

Вы можете переписать весь запрос на это для лучшей производительности, сценарий от Joao должен исправили вашу описанную ошибку:

;WITH CTE as 
(
    SELECT 
    mostrecent, 
    row_number() over (partition by level order by somedate desc) rn 
    FROM t2 
) 
UPDATE CTE 
SET 
    mostrecent = 0 
WHERE 
    mostrecent = 1 
    and rn > 1 
+0

Я согласен с тем, что мой первоначальный подход - немного klunky; Мне нужно улучшиться в Common Table Expressions, XML Path и CLR Assemblies, и ... список можно продолжить. –

+0

@ t-clausen.dk есть ли какое-либо преимущество в производительности между использованием CTE или использованием UPDATE ... FROM (используя вашу таблицу в предложении FROM)? –

+0

@JoaoLeal оба метода используют обновления, используя этот метод. Я избегаю подвыборки внутри подзапроса, он также имеет лучшую читаемость и обновляет меньшее количество строк. Да, он будет работать быстрее –

Смежные вопросы