Как мне (или Могу ли я) выбрать DISTINCT на нескольких столбцах?
Мне нужно получить все строки из таблицы, где объединены 2 столбца, все разные. Поэтому я хочу, чтобы все продажи, которые не имеют никаких других продаж, которые произошли в тот же день по той же цене. Продажи, которые уникальны в зависимости от дня и цены, будут обновлены до активного статуса.
поэтому я думаю:
UPDATE sales
SET status = 'ACTIVE'
WHERE id IN (SELECT DISTINCT (saleprice, saledate), id, count(id)
FROM sales
HAVING count = 1)
но мой мозг болит идти дальше этого.
4 ответов
SELECT DISTINCT a,b,c FROM t
is примерно эквивалентно:
SELECT a,b,c FROM t GROUP BY a,b,c
это хорошая идея, чтобы привыкнуть к группе по синтаксису, так как она более мощная.
для вашего запроса я бы сделал это так:
UPDATE sales
SET status='ACTIVE'
WHERE id IN
(
SELECT id
FROM sales S
INNER JOIN
(
SELECT saleprice, saledate
FROM sales
GROUP BY saleprice, saledate
HAVING COUNT(*) = 1
) T
ON S.saleprice=T.saleprice AND s.saledate=T.saledate
)
если вы соберете ответы до сих пор, очистите и улучшите, вы получите этот превосходный запрос:
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).
но это все еще далеко от оптимального. Используйте NOT EXISTS
(anti-)semi-join для еще лучшей производительности. EXISTS
стандартный SQL, имеет был вокруг навсегда (по крайней мере, с PostgreSQL 7.2, задолго до того, как этот вопрос был задан) и идеально подходит для представленных требований:
UPDATE sales s
SET status = 'ACTIVE'
WHERE NOT EXISTS (
SELECT 1
FROM sales s1
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
уникальный ключ для идентификации строки
если у вас нет первичного или уникального ключа для таблицы (id
в примере), вы можете заменить столбец системы ctid
для целей этого запроса (но не для некоторых других цели):
AND s1.ctid <> s.ctid
каждая таблица должна иметь первичный ключ. Добавьте один, если у вас его еще нет. Я предлагаю serial
или
проблема с вашим запросом заключается в том, что при использовании предложения GROUP BY (которое вы по существу делаете с помощью distinct) вы можете использовать только столбцы, которые вы группируете по или агрегатные функции. Вы не можете использовать идентификатор столбца, поскольку существуют потенциально разные значения. В вашем случае всегда есть только одно значение из-за предложения HAVING, но большинство СУБД недостаточно умны, чтобы распознать это.
Это должно работать (и не требует соединения):
UPDATE sales
SET status='ACTIVE'
WHERE id IN (
SELECT MIN(id) FROM sales
GROUP BY saleprice, saledate
HAVING COUNT(id) = 1
)
вы могли также используйте MAX или AVG вместо MIN, важно использовать функцию, которая возвращает значение столбца, если есть только одна соответствующая строка.
Я хочу выбрать различные значения из одного столбца "GrondOfLucht", но они должны быть отсортированы в порядке, указанном в столбце "сортировка". Я не могу получить различные значения только одного столбца, используя
Select distinct GrondOfLucht,sortering
from CorWijzeVanAanleg
order by sortering
Это также даст sortering колонка ' и потому что 'GrondOfLucht' и 'sortering' не является уникальным, то результатом будут все строки.
использовать группу для выбора записей из GrondOfLucht в порядке, указанном на sortering
SELECT GrondOfLucht
FROM dbo.CorWijzeVanAanleg
GROUP BY GrondOfLucht, sortering
ORDER BY MIN(sortering)