Выбор столбцов с DISTINCT в PostgreSQL

Я запрашиваю автобусные остановки из базы данных и хочу, чтобы она возвращала только 1 остановку на автобусную линию/направление. Этот запрос делает именно это:

Stop.select("DISTINCT line_id, direction")

За исключением того, что он не даст мне никакого другого атрибута, кроме этих 2. Я попробовал пару других запросов, чтобы он возвращал id в дополнение к полям line_id и direction (в идеале он вернул бы все столбцы), но безуспешно:

Stop.select("DISTINCT line_id, direction, id")

а также

Stop.select("DISTINCT(line_id || '-' || direction), id")

В обоих случаях запрос теряет отдельное предложение и возвращаются все строки.

Какой-то классный чувак помог мне и предложил использовать подзапрос, чтобы он возвращал все идентификаторы:

Stop.find_by_sql("SELECT DISTINCT a1.line_id, a1.direction, (SELECT a2.id from stops a2 where a2.line_id = a1.line_id AND a2.direction = a1.direction ORDER BY a2.id ASC LIMIT 1) as id FROM stops a1

Затем я могу извлечь все идентификаторы и выполнить второй запрос, чтобы получить полные атрибуты для каждой остановки.

Есть ли способ, чтобы все это было внутри 1 запроса и возвращало все атрибуты?


person samvermette    schedule 15.02.2011    source источник
comment
Я не уверен, что ваш вопрос имеет какой-либо смысл. Либо ты хочешь остановки, либо нет. Будет больше рядов, если вы хотите остановки. Если вы хотите, чтобы идентификаторы остановки в столбцах обернули array_agg вокруг подзапроса и сняли ограничение. Кажется, после этого у вас будет какой-то запрос или почему просто вернуть stop_ids. Я думаю, что лучше всего указать, что нужно в вопросе. Людям может быть намного проще ответить   -  person nate c    schedule 16.02.2011
comment
Мне нужны остановки, только одна на линию/направление. Итак, если автобусная линия имеет 2 направления, я хочу, чтобы запрос возвращал 1 остановку для каждого направления. Ответ @pothibo правильный, все равно спасибо.   -  person samvermette    schedule 16.02.2011


Ответы (2)


Не так быстро. В другом ответе выбран произвольный stop_id.

Вот почему ваш вопрос не имеет смысла. Мы можем вытащить stop_ids и иметь отдельный line_id и направление. Но мы понятия не имеем, почему у нас есть этот stop_id.

    create temp table test( line_id integer, direction char(1), stop_id      integer);
    insert into test values
            (1, 'N', 1),
            (1, 'N', 2),
            (1, 'S', 1),
            (1, 'S', 2),
            (2, 'N', 1),
            (2, 'N', 2),
            (2, 'S', 1),
            (2, 'S', 2)
    ;
    select distinct on (line_id, direction) * from test;
    -- do this again but will reverse the order of stop_ids
    -- could it possible change our Robust Query?!!!
    drop table test;
    create temp table test(line_id integer,direction char(1),stop_id integer);
    insert into test values
            (1, 'N', 2),
            (1, 'N', 1),
            (1, 'S', 2),
            (1, 'S', 1),
            (2, 'N', 2),
            (2, 'N', 1),
            (2, 'S', 2),
            (2, 'S', 1)
    ;
    select distinct on (line_id, direction) * from test;

Сначала выберите:

line_id | direction | stop_id 
---------+-----------+---------
       1 | N         |       1
       1 | S         |       1
       2 | N         |       1
       2 | S         |       1

Второй выбор:

line_id | direction | stop_id 
---------+-----------+---------
       1 | N         |       2
       1 | S         |       2
       2 | N         |       2
       2 | S         |       2

Итак, мы обошлись без группировки stop_id, но у нас нет гарантий, почему мы получили тот, который сделали. Все, что мы знаем, это то, что это допустимый stop_id. Любые обновления, вставки и другие вещи, которые не гарантирует никакая RDMS, могут изменить физический порядок строк.

Именно это я и имел в виду в верхнем комментарии. Нет никакой известной причины перетаскивать один stop_id поверх другого, но почему-то вам отчаянно нужен этот stop_id (или что-то еще).

person nate c    schedule 16.02.2011
comment
Попался. В моем случае я собираюсь упорядочить результаты по расстоянию от пользователя. Обязательно ли при добавлении предложения ORDER BY будет выбран первый stop_id? - person samvermette; 16.02.2011
comment
Ваше предупреждение имеет силу. Но вопрос был не в достоверности результата. Дело было в том, что сам запрос был неправильным. Я предполагаю, что этот запрос является простым тестом, а не фактическим запросом. - person Pier-Olivier Thibault; 16.02.2011

person    schedule
comment
отлично. такого раньше не видел. Вопрос был специфичен для Postgres, поэтому этот ответ хорош, но стоит отметить, что похоже, что это ответ, специфичный для Postgres postgresql.org/docs/8.1/static/queries-select-lists.html - person digitaljoel; 16.02.2011
comment
На самом деле 'DISTINCT (line_id, direction), *' у меня тоже работает с postgres - person Nico; 16.11.2011