SQL: сохранить порядок подзапросов во внешнем запросе

У меня проблемы с попыткой объединить DISTINCT и ORDER BY. У меня есть таблица Users со следующими атрибутами id, name и у меня есть таблица Purchases со следующими атрибутами id,user_id,date_purchased,returned

Я хочу получить все уникальные Users, которые имеют returned Purchase, отсортированные по date_purchased.

Вот некоторые примерные данные

Users
id | name 
---+-----------
 1 | Bob
 2 | John
 3 | Bill
 4 | Frank
 5 | Fred
 6 | Al

Purchases
      id |      user_id     |  startdate | returned 
    -----+------------------+------------+---------------
     100 | 1                | 2015-02-06 |          true
     101 | 1                | 2015-01-06 |          true
     102 | 1                | 2015-02-05 |          false
     103 | 2                | 2015-02-05 |          false
     104 | 2                | 2015-02-05 |          false
     105 | 3                | 2015-01-05 |          true
     106 | 3                | 2015-02-04 |          true
     107 | 4                | 2015-01-07 |          true
     108 | 5                | 2015-02-05 |          false
     109 | 6                | 2015-02-07 |          false
     110 | 6                | 2015-01-05 |          true

Результатом должен быть следующий идентификатор пользователя 1,3,4,6

Вот запрос, который я написал

SELECT DISTINCT (id) FROM (
   SELECT users.id as id, purchases.startdate FROM
   users INNER JOIN purchases on users.id=purchases.id
   WHERE returned=true
   ORDER BY startdate )

Этот запрос правильно возвращает результаты; однако это в неправильном порядке. Читая другие ответы, я обнаружил, что вы не можете поддерживать порядок подзапросов. Я попытался переместить порядок во внешний запрос; однако startdate также должен присутствовать в запросе выбора, и это не то, что я хочу


person user2158382    schedule 06.02.2015    source источник
comment
Непонятно, на какой вопрос вы хотите ответить. С каждой покупкой связан startdate, и один пользователь может вернуть несколько покупок. По какому startdate вы хотите упорядочить результаты?   -  person John Bollinger    schedule 06.02.2015


Ответы (2)


Просто удалите подзапрос и используйте GROUP BY:

SELECT u.id as id
FROM users u INNER JOIN
     purchases p
     on u.id = p.id
WHERE returned = true
GROUP BY u.id
ORDER BY MIN(startdate);

Вы можете полагаться только на то, что набор результатов находится в определенном порядке, когда вы используете ORDER BY для самого внешнего SELECT. В любом другом случае нет гарантии заказа.

В качестве примечания: порядок обычно работает с подзапросом (к сожалению, потому что многие люди смотрят на результаты некоторых запросов и обобщают их все). Проблема в этом случае заключается в distinct. Он переупорядочивает данные (то есть сортирует их) для удаления дубликатов.

person Gordon Linoff    schedule 06.02.2015

Сценарий Гордона дает вам нужные данные, но чтобы ответить на ваш вопрос о том, как поддерживать порядок подзапроса, вы можете извлечь столбец, который вы хотите упорядочить, из подзапроса и затем упорядочить по нему.

SELECT DISTINCT (id), innerTable.startdate FROM (
   SELECT users.id as id, purchases.startdate FROM
   users INNER JOIN purchases on users.id=purchases.id
   WHERE returned=true) as innerTable
   ORDER BY innerTable.startdate
person LCIII    schedule 06.02.2015
comment
Им нужны только разные идентификаторы, в то время как ваш запрос извлекает разные комбинации id и startdate. (Заключение id в скобки не говорит серверу базы данных, что вы хотите, чтобы различались только id: DISTINCT всегда применяется ко всем строкам.) - person Andriy M; 19.02.2015