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, но я не хочу, чтобы они как-то фильтровались.

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

NovumCoder
источник

Ответы:

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
Дэвид Джаши
источник
2
Небольшое
@Novum Нет. Это означает, что кошка берет значение идентификатора из одной строки Майкла, а метаданные - из другой, поскольку она запрашивала максимальные значения Майкла.
Clodoaldo Neto
Ну да, это сильно зависит от реальных данных, которые использует OP, о которых я совершенно не осведомлен. Возможно, вам понадобится использовать MIN или что-то еще. Только что продемонстрировал, как можно включать поля не в GROUP BYпредложение.
Дэвид Джаши
Это не лучшее решение, потому что разные значения из разных строк будут смешиваться.
Эллиот Ченс