Postgres: Отдельно, но только для одного столбца


121

У меня есть таблица на pgsql с именами (имеющая более 1 миллиона строк), но у меня также есть много дубликатов. Я выбираю 3 поля: id, name, metadata.

Я хочу выбрать их случайным образом с помощью ORDER BY RANDOM()и LIMIT 1000, поэтому я делаю это много шагов, чтобы сэкономить немного памяти в моем скрипте PHP.

Но как я могу это сделать, чтобы он давал мне только список, не имеющий дубликатов в именах.

Например [1,"Michael Fox","2003-03-03,34,M,4545"]будет возвращено, но нет [2,"Michael Fox","1989-02-23,M,5633"]. Поле имени является наиболее важным и должно быть уникальным в списке каждый раз, когда я выбираю, и оно должно быть случайным.

Я пробовал с GROUP BY name, но тогда он ожидает, что у меня будут идентификатор и метаданные GROUP BYтакже или в функции aggragate, но я не хочу, чтобы они как-то фильтровались.

Кто-нибудь знает, как получить много столбцов, но сделать только отдельный столбец?

Ответы:


226

Чтобы сделать различное только для одного (или n) столбцов:

select distinct on (name)
    name, col1, col2
from names

Это вернет любую из строк, содержащих имя. Если вы хотите контролировать, какие из строк будут возвращены, вам необходимо заказать:

select distinct on (name)
    name, col1, col2
from names
order by name, col1

Вернет первую строку при заказе по col1.

distinct on:

SELECT DISTINCT ON (выражение [, ...]) сохраняет только первую строку каждого набора строк, в которых данные выражения оцениваются как равные. Выражения DISTINCT ON интерпретируются с использованием тех же правил, что и для ORDER BY (см. Выше). Обратите внимание, что «первая строка» каждого набора непредсказуема, если только ORDER BY не используется, чтобы гарантировать, что нужная строка появится первой.

Выражение (-я) DISTINCT ON должно соответствовать крайнему левому выражению (-ям) ORDER BY. Предложение ORDER BY обычно содержит дополнительные выражения, которые определяют желаемый приоритет строк в каждой группе DISTINCT ON.


Хороший улов при заказе. Я не включил это, потому что они упомянули о случайном порядке, но в любом случае это важно упомянуть.
Craig Ringer

Является ли order by nameтребуется? Будет ли это давать другой результат order by col1?
Эллиот Ченс

1
@elliot да nameнадо. Проверьте distinct onв руководстве.
Клодоальдо Нето

1
Я бы хотел, чтобы команда TSQL могла предоставить такой разумный способ сделать это.
JTW 08

Пожалуйста, добавьте соответствующую ссылку на
Ogaga Uzoh

17

Кто-нибудь знает, как получить много столбцов, но сделать только отдельный столбец?

Вы хотите , чтобы в DISTINCT ONпункт .

Вы не предоставили образцы данных или полный запрос, поэтому мне нечего вам показать. Вы хотите написать что-то вроде:

SELECT DISTINCT ON (name) fields, id, name, metadata FROM the_table;

Это вернет непредсказуемый (но не «случайный») набор строк. Если вы хотите сделать его предсказуемым, добавьте ORDER BYответ Клодальдо. Если вы хотите сделать его по-настоящему случайным, вы захотите ORDER BY random().


Просто обратите внимание, что с этим предложением DISTINCT ON вы можете ЗАКАЗАТЬ только то же самое и многое другое. Итак, если вы скажете DISTINCT ON (имя), вы должны ЗАКАЗАТЬ ПО имени, а затем по любому другому запросу. Вряд ли идеал.
Кевин Паркер,

Кевин, вы можете просто использовать CTE или подзапрос-in-FROM и ORDER BY во внешнем запросе
Крейг Рингер,

Да, и наблюдайте за производительностью ... Будут изучены все возможные результаты из индексного пространства. Оказывается , что может быть 10-20ms запрос с правом индекса в 900ms один только потому , что posgres не может обрабатывать различные отчетливое / заказ на. Даже не имеет значения, каков внешний порядок запроса, он будет использовать индекс из внутреннего подзапроса, чтобы сначала найти совпадения, а затем выполнить повторную сортировку. С радостью
Кевин Паркер

4
SELECT NAME,MAX(ID) as ID,MAX(METADATA) as METADATA 
from SOMETABLE
GROUP BY NAME


@Novum Нет. Это означает, что кошка берет значение идентификатора из одной строки Майкла, а метаданные - из другой, поскольку она запрашивала максимальные значения Майкла.
Clodoaldo Neto

Ну да, это сильно зависит от реальных данных, которые использует OP, о которых я совершенно не осведомлен. Возможно, вам понадобится использовать MIN или что-то еще. Только что продемонстрировал, как можно включать поля не в GROUP BYпредложение.
Дэвид Джаши

Это не лучшее решение, потому что разные значения из разных строк будут смешиваться.
Эллиот Ченс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.