Если вы соберете ответы, очистите и улучшите их, вы получите следующий превосходный запрос:
UPDATE sales
SET status = 'ACTIVE'
WHERE (saleprice, saledate) IN (
SELECT saleprice, saledate
FROM sales
GROUP BY saleprice, saledate
HAVING count(*) = 1
);
, который на намного быстрее, чем любой из них. Уменьшает производительность принятого в настоящее время ответа в 10-15 раз (в моих тестах на PostgreSQL 8.4 и 9.1).
1146 Но это все еще далеко от оптимального. Используйте NOT EXISTS
(анти-) полусоединение для еще лучшей производительности. EXISTS
является стандартным SQL, существует вечно (по крайней мере, с PostgreSQL 7.2, задолго до того, как был задан этот вопрос) и идеально соответствует представленным требованиям:
UPDATE sales s
SET status = 'ACTIVE'
WHERE NOT EXISTS (
SELECT FROM sales s1 -- SELECT list can be empty for EXISTS
WHERE s.saleprice = s1.saleprice
AND s.saledate = s1.saledate
AND s.id <> s1.id -- except for row itself
)
AND s.status IS DISTINCT FROM 'ACTIVE'; -- avoid empty updates. see below
db <> fiddle здесь
Старая скрипта SQL
Если у вас нет основного или уникального Ключ для таблицы (id
в примере), вы можете заменить системный столбец ctid
для целей этого запроса (но не для некоторых других целей):
AND s1.ctid <> s.ctid
Каждая таблица должна иметь первичный ключ. Добавьте еще один, если у вас его еще не было. Я предлагаю столбец serial
или IDENTITY
в Postgres 10+.
Связанные:
Подзапрос в EXISTS
anti-semi-join может перестать оценивать, как только будет найден первый дуплекс (нет смысла смотреть дальше). Для базовой таблицы с небольшим количеством дубликатов это лишь немного более эффективно. С большим количеством дубликатов это становится способом более эффективным.
Для строк, в которых уже есть status = 'ACTIVE'
, это обновление ничего не изменит, но все равно вставит новую версию строки за полную стоимость (применяются незначительные исключения). Обычно вы этого не хотите. Добавьте еще одно условие WHERE
, как показано выше, чтобы избежать этого и сделать его еще быстрее:
Если определено status
NOT NULL
, вы можете упростить до:
AND status <> 'ACTIVE';
Этот запрос (в отличие от принятого в настоящее время ответа Джоэля ) не рассматривает значения NULL как равные. Следующие две строки для (saleprice, saledate)
будут квалифицироваться как «отличные» (хотя они выглядят идентично человеческому глазу):
(123, NULL)
(123, NULL)
Также передает уникальный индекс и почти в любом другом месте, поскольку значения NULL не сравниваются равен по стандарту SQL. См.
OTOH, GROUP BY
, DISTINCT
или DISTINCT ON ()
обрабатывают значения NULL как равные , Используйте соответствующий стиль запроса в зависимости от того, чего вы хотите достичь. Вы все еще можете использовать этот более быстрый запрос с IS NOT DISTINCT FROM
вместо =
для любого или всех сравнений, чтобы сделать сравнение NULL равным. Подробнее:
Если все сравниваемые столбцы определены NOT NULL
, в нем нет места разногласие. [тысяча сто пятьдесят семь]
Я делал:
NSDateFormatter* theDateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[theDateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[theDateFormatter setDateFormat:@"EEEE"];
NSString *weekDay = [theDateFormatter stringFromDate:[NSDate date]];
У этого есть дополнительный бонус, позволяющий вам выбрать способ возврата дня недели (путем изменения строки формата даты в setDateFormat: call
Дополнительную информацию см. По адресу:
Вы можете взглянуть на классы NSDate и NSCalendar. Например, здесь и здесь
Они предоставляют следующий код:
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *weekdayComponents =
[gregorian components:(NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:today];
NSInteger day = [weekdayComponents day];
NSInteger weekday = [weekdayComponents weekday];
Используйте NSCalendar и NSDateComponents. Как показано в документации NSDateComponents:
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
NSDateComponents *weekdayComponents = [gregorian components:NSWeekdayCalendarUnit fromDate:date];
int weekday = [weekdayComponents weekday];