Мне нужно извлечь все строки из таблицы, где 2 столбца вместе все разные. Поэтому я хочу, чтобы все продажи, в которых не было других продаж, произошли в тот же день по той же цене. Продажи, которые являются уникальными в зависимости от дня и цены, будут обновлены до активного статуса.
Вот я и думаю:
UPDATE sales
SET status = 'ACTIVE'
WHERE id IN (SELECT DISTINCT (saleprice, saledate), id, count(id)
FROM sales
HAVING count = 1)
Но мой мозг болит дальше.
Если вы соберете ответы, очистите и улучшите их, вы получите этот превосходный запрос:
Который намного быстрее, чем любой из них. Снижает производительность принятого в настоящее время ответа в 10-15 раз (в моих тестах на PostgreSQL 8.4 и 9.1).
Но это все еще далеко от оптимального. Используйте
NOT EXISTS
(анти) полусоединение для еще лучшей производительности.EXISTS
является стандартным SQL, существует вечно (по крайней мере, с PostgreSQL 7.2, задолго до того, как был задан этот вопрос) и идеально соответствует представленным требованиям:db <> скрипеть здесь
Old SQL Fiddle
Уникальный ключ для идентификации строки
Если у вас нет первичного или уникального ключа для таблицы (
id
в примере), вы можете заменить системный столбецctid
для целей этого запроса (но не для некоторых других целей):Каждая таблица должна иметь первичный ключ. Добавьте еще один, если у вас его еще не было. Я предлагаю
serial
илиIDENTITY
столбец в Postgres 10+.Связанные с:
Как это быстрее?
Подзапрос в
EXISTS
анти-полусоединении может прекратить оценку, как только будет найден первый дублик (нет смысла смотреть дальше). Для базовой таблицы с небольшим количеством дубликатов это немного более эффективно. С большим количеством дубликатов это становится намного более эффективным.Исключить пустые обновления
Для строк, которые уже имеют
status = 'ACTIVE'
это обновление, ничего не изменится, но все равно будет вставлена новая версия строки за полную стоимость (применяются незначительные исключения). Обычно вы этого не хотите. Добавьте еще одноWHERE
условие, как показано выше, чтобы избежать этого и сделать его еще быстрее:Если
status
определеноNOT NULL
, вы можете упростить до:Тип данных столбца должен поддерживать
<>
оператор. Некоторые типы, какjson
нет. Видеть:Тонкая разница в обработке NULL
Этот запрос (в отличие от принятого в настоящее время ответа Джоэла ) не рассматривает значения NULL как равные. Следующие две строки для
(saleprice, saledate)
будут квалифицироваться как «отличные» (хотя выглядят идентично человеческому глазу):Также передает уникальный индекс и почти где-либо еще, поскольку значения NULL не сравниваются равными в соответствии со стандартом SQL. Видеть:
Ото,
GROUP BY
,DISTINCT
илиDISTINCT ON ()
значения NULL , как лечить равны. Используйте соответствующий стиль запроса в зависимости от того, чего вы хотите достичь. Вы можете по-прежнему использовать этот более быстрый запросIS NOT DISTINCT FROM
вместо=
любого или всех сравнений, чтобы сделать сравнение NULL равным. Больше:Если все сравниваемые столбцы определены
NOT NULL
, нет места для разногласий.источник
count(*)
является более эффективным , чемcount(<expression>)
. Просто попробуйте. Postgres имеет более быструю реализацию для этого варианта агрегатной функции. Может быть, вы путаете Postgres с какой-то другой RDBMS?Проблема с вашим запросом состоит в том, что при использовании предложения GROUP BY (которое вы по сути делаете с помощью различных) вы можете использовать только столбцы, которые вы группируете или объединяете функции. Вы не можете использовать идентификатор столбца, потому что есть потенциально разные значения. В вашем случае всегда есть только одно значение из-за предложения HAVING, но большинство СУБД недостаточно умны, чтобы это распознать.
Это должно работать, однако (и не нуждается в соединении):
Вы также можете использовать MAX или AVG вместо MIN, важно использовать только функцию, которая возвращает значение столбца, если есть только одна совпадающая строка.
источник
Я хочу выбрать отдельные значения из одного столбца «GrondOfLucht», но они должны быть отсортированы в порядке, указанном в столбце «сортировка». Я не могу получить отдельные значения только одного столбца, используя
Это также даст столбцу «сортировка», и поскольку «GrondOfLucht» И «сортировка» не уникальны, результатом будут ВСЕ строки.
используйте ГРУППУ, чтобы выбрать записи 'GrondOfLucht' в порядке, заданном сортировкой
источник
Если ваша СУБД не поддерживает различные с несколькими столбцами, как это:
Multi select в целом можно выполнить безопасно следующим образом:
Поскольку это может работать на большинстве СУБД, и ожидается, что это будет быстрее, чем группировка по решению, поскольку вы избегаете функциональности группировки.
источник