Постгреси: чіткі, але лише для одного стовпця


120

У мене є таблиця 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матиму ідентифікатори та метадані як у функції, так і в агрегаті, але я не хочу, щоб вони якось фільтрувались.

Хтось знає, як отримати багато стовпців, але зробити лише окремий на одному стовпчику?

Відповіді:


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.


Хороший улов на замовлення. Я не включив його, оскільки вони згадали про те, що хочуть випадкового впорядкування, але важливо все-таки згадати.
Крейг Рінгер

Чи order by nameпотрібне? Чи це призведе до іншого результату order by col1?
Шанс Елліот

1
@elliot так nameпотрібно. Перевірте distinct onв посібнику.
Clodoaldo Neto

1
Я хочу, щоб команда TSQL могла надати такий розумний спосіб зробити це.
JTW

Будь ласка, додайте відповідну посилання на
Ogaga Uzoh

17

Хтось знає, як отримати багато стовпців, але зробити лише окремий на одному стовпчику?

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

Ви не надали зразкові дані чи повний запит, тому я не маю нічого вам показати. Ви хочете написати щось на кшталт:

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

Це поверне непередбачуваний (але не "випадковий") набір рядків. Якщо ви хочете зробити це передбачуваним, додайте ORDER BYвідповідь Clodaldo. Якщо ви хочете зробити це по-справжньому випадковим, вам захочеться ORDER BY random().


Просто зауважте з цим пунктом DISTINCT ON, ви можете ЗАМОВИТИ тільки те саме + більше. Тож якщо ви скажете ВІДМИЩЕННЯ (ім'я), ви повинні ЗАМОВИТИ ІМЯ, а потім все, що завгодно. Навряд чи ідеально.
Кевін Паркер

Кевіне, ви можете просто використовувати CTE або підзапросити ВІД і ЗАМОВИТИ в зовнішньому запиті
Крейг Рінгер

Так, і слідкуйте за тим, як продуктивність буде проходити ... Буде здійснено пошук усіх можливих результатів з простору індексу. Це перетворює те, що може бути запит за 10-20 м з правильним індексом у 900 м, лише тому, що posgres не може обробляти інший чіткий / порядок. Навіть не важливо, яким є порядок зовнішнього запиту, він використовуватиме індекс із внутрішнього підзапиту, щоб спочатку знайти збіги, а потім повторно сортувати. Раді
Кевін Паркер

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

2
Лише застереження: це може не повернути значення ідентифікатора чи значення метаданих, які належать "разом"
a_horse_with_no_name

@Novum Ні. Це означає, що кішка приймає значення id з одного з рядків Майкла та метаданих з іншого, як його запитували про максимуми Майкла.
Clodoaldo Neto

Ну так, це дуже залежить від реального використання ОП даних, про які я абсолютно не знаю. Можливо, вам доведеться використовувати MIN або будь-яку іншу. Щойно продемонстровано, як можна включити поля не до GROUP BYпункту.
Девід Яші

Це не гарне рішення, оскільки різні значення з різних рядків змішаться.
Шанс Елліот
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.