Thread: Сортировка в требуемом порядке

Сортировка в требуемом порядке

From
Олекс й Василь в
Date:
Есть такой запрос:
Select * from foo where catalog_id IN(2,3,6,1,4,66,44,23,45)

Возможно ли вывести результат в таком же порядке, как и условие в IN, тоесть первый елемент с  catalog_id == 2, второй - catalog_id == 3, третий - catalog_id == 6, четвертый - catalog_id == 1 и т.д. 

Re: Сортировка в требуемом порядке

From
"Dmitry E. Oboukhov"
Date:
ОйВв> Есть такой запрос:
ОйВв> Select * from foo where catalog_id IN(2,3,6,1,4,66,44,23,45)

ОйВв> Возможно ли вывести результат в таком же порядке, как и условие в IN, тоесть
ОйВв> первый елемент с  catalog_id == 2, второй - catalog_id == 3, третий
ОйВв> - catalog_id == 6, четвертый - catalog_id == 1 и т.д.

скорее всего нет. когда таблица просматривается на предмет выборки
строк то проверяется условие WHERE, а то в каком порядке это условие
написано роли не играет, важно TRUE/FALSE ли оно возвращает.

можно сортирнуть в хранимой процедуре или после выборки, имхо
--

. ''`.                               Dmitry E. Oboukhov
: :’  :   email: unera@debian.org jabber://UNera@uvw.ru
`. `~’              GPGKey: 1024D / F8E26537 2006-11-21
  `- 1B23 D4F8 8EC0 D902 0555  E438 AB8C 00CF F8E2 6537

Attachment

Re: [pgsql-ru-general] Сортировка в требуемом порядке

From
Dmitriy Igrishin
Date:
Приветствую,

14 марта 2011 г. 17:20 пользователь Олекс й Василь в <leopard_ne@inbox.ru> написал:
Есть такой запрос:
Select * from foo where catalog_id IN(2,3,6,1,4,66,44,23,45)

Возможно ли вывести результат в таком же порядке, как и условие в IN, тоесть первый елемент с  catalog_id == 2, второй - catalog_id == 3, третий - catalog_id == 6, четвертый - catalog_id == 1 и т.д. 
Данную задачу можно решить, заменив IN на JOIN, например:

dmitigr=>
SELECT foo.* FROM (VALUES(1),(2),(3),(4),(6)) AS foo(catalog_id)
  JOIN (SELECT id.val, row_number() over() FROM (VALUES(3),(2),(6),(1),(4)) AS id(val)) AS id
  ON (foo.catalog_id = id.val) ORDER BY row_number;
 catalog_id
------------
          3
          2
          6
          1
          4

В этом примере foo - исходная таблица с данными,
id - псевдотаблица с 2-мя столбцами: значение (собственно id)
и его порядковый номер.

--
// Dmitriy.


Re: Re: [pgsql-ru-general] Сортировка в требуемом порядке

From
"Dmitry E. Oboukhov"
Date:
DI> 14 марта 2011 г. 17:20 пользователь Олекс й Василь в <leopard_ne@inbox.ru>
DI> написал:

DI> Есть такой запрос:
DI> Select * from foo where catalog_id IN(2,3,6,1,4,66,44,23,45)

DI> Возможно ли вывести результат в таком же порядке, как и условие в IN,
DI> тоесть первый елемент с  catalog_id == 2, второй - catalog_id == 3, третий
DI> - catalog_id == 6, четвертый - catalog_id == 1 и т.д.

DI> Данную задачу можно решить, заменив IN на JOIN, например:

DI> dmitigr=>
DI> SELECT foo.* FROM (VALUES(1),(2),(3),(4),(6)) AS foo(catalog_id)
DI> JOIN (SELECT id.val, row_number() over() FROM (VALUES(3),(2),(6),(1),(4)) AS
DI> id(val)) AS id
DI> ON (foo.catalog_id = id.val) ORDER BY row_number;
DI> catalog_id
DI> ------------
DI> 3
DI> 2
DI> 6
DI> 1
DI> 4


кстати unnest как-то даже покороче выглядит

SELECT
    foo.*

FROM
    unnest('{3,2,6,1,4}'::int[]) idt

JOIN
    foo ON catalog_id = idt

WHERE
    foo.id IS NOT NULL;

и от сортировки можно избавиться

хотя может оптимизатор ее и сам выбросит.

DI> В этом примере foo - исходная таблица с данными,
DI> id - псевдотаблица с 2-мя столбцами: значение (собственно id)
DI> и его порядковый номер.
--

. ''`.                               Dmitry E. Oboukhov
: :’  :   email: unera@debian.org jabber://UNera@uvw.ru
`. `~’              GPGKey: 1024D / F8E26537 2006-11-21
  `- 1B23 D4F8 8EC0 D902 0555  E438 AB8C 00CF F8E2 6537

Attachment

Re: Re: [pgsql-ru-general] Сортировка в требуемом порядке

From
"Dmitry E. Oboukhov"
Date:
On 22:22 Mon 14 Mar     , Dmitry E. Oboukhov wrote:

DI>> 14 марта 2011 г. 17:20 пользователь Олекс й Василь в <leopard_ne@inbox.ru>
DI>> написал:

DI>> Есть такой запрос:
DI>> Select * from foo where catalog_id IN(2,3,6,1,4,66,44,23,45)

DI>> Возможно ли вывести результат в таком же порядке, как и условие в IN,
DI>> тоесть первый елемент с  catalog_id == 2, второй - catalog_id == 3, третий
DI>> - catalog_id == 6, четвертый - catalog_id == 1 и т.д.

DI>> Данную задачу можно решить, заменив IN на JOIN, например:

DI>> dmitigr=>
DI>> SELECT foo.* FROM (VALUES(1),(2),(3),(4),(6)) AS foo(catalog_id)
DI>> JOIN (SELECT id.val, row_number() over() FROM (VALUES(3),(2),(6),(1),(4)) AS
DI>> id(val)) AS id
DI>> ON (foo.catalog_id = id.val) ORDER BY row_number;
DI>> catalog_id
DI>> ------------
DI>> 3
DI>> 2
DI>> 6
DI>> 1
DI>> 4

Tprgpo> кстати unnest как-то даже покороче выглядит

Tprgpo> SELECT
Tprgpo> foo.*

Tprgpo> FROM
Tprgpo> unnest('{3,2,6,1,4}'::int[]) idt

Tprgpo> JOIN
Tprgpo> foo ON catalog_id = idt

Tprgpo> WHERE
Tprgpo> foo.id IS NOT NULL;

WHERE конечно же не нужен, WHERE это если LEFT JOIN :)

--

. ''`.                               Dmitry E. Oboukhov
: :’  :   email: unera@debian.org jabber://UNera@uvw.ru
`. `~’              GPGKey: 1024D / F8E26537 2006-11-21
  `- 1B23 D4F8 8EC0 D902 0555  E438 AB8C 00CF F8E2 6537

Attachment


14 марта 2011 г. 22:22 пользователь Dmitry E. Oboukhov <unera@debian.org> написал:

DI> 14 марта 2011 г. 17:20 пользователь Олекс й Василь в <leopard_ne@inbox.ru>
DI> написал:

DI> Есть такой запрос:
DI> Select * from foo where catalog_id IN(2,3,6,1,4,66,44,23,45)

DI> Возможно ли вывести результат в таком же порядке, как и условие в IN,
DI> тоесть первый елемент с  catalog_id == 2, второй - catalog_id == 3, третий
DI> - catalog_id == 6, четвертый - catalog_id == 1 и т.д.

DI> Данную задачу можно решить, заменив IN на JOIN, например:

DI> dmitigr=>
DI> SELECT foo.* FROM (VALUES(1),(2),(3),(4),(6)) AS foo(catalog_id)
DI> JOIN (SELECT id.val, row_number() over() FROM (VALUES(3),(2),(6),(1),(4)) AS
DI> id(val)) AS id
DI> ON (foo.catalog_id = id.val) ORDER BY row_number;
DI> catalog_id
DI> ------------
DI> 3
DI> 2
DI> 6
DI> 1
DI> 4


кстати unnest как-то даже покороче выглядит

SELECT
   foo.*

FROM
   unnest('{3,2,6,1,4}'::int[]) idt

JOIN
   foo ON catalog_id = idt

WHERE
   foo.id IS NOT NULL;

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

хотя может оптимизатор ее и сам выбросит.

DI> В этом примере foo - исходная таблица с данными,
DI> id - псевдотаблица с 2-мя столбцами: значение (собственно id)
DI> и его порядковый номер.
--

. ''`.                               Dmitry E. Oboukhov
: :’  :   email: unera@debian.org jabber://UNera@uvw.ru
`. `~’              GPGKey: 1024D / F8E26537 2006-11-21
 `- 1B23 D4F8 8EC0 D902 0555  E438 AB8C 00CF F8E2 6537



--
// Dmitriy.


DI> К сожалению, нигде не сказано, что unnest() обязан
DI> вернуть набор элементов, сохраняя упорядоченность,
DI> заданную в массиве. Предполагать и располагать -
DI> суть разные подходы :-)

Вероятно Вы правы, однако мне крайне сложно представить себе
реализацию функции преобразования матрицы вида
[ 1 2 3 ]
в матрицу вида
[
  1
  2
  3
]

чтобы при этом мог пострадать порядок следования. это разве что
специально что-то делать надо?

DI> Кроме того, может возникнуть задача выбрать элементы
DI> в обратном порядке.

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

--

. ''`.                               Dmitry E. Oboukhov
: :’  :   email: unera@debian.org jabber://UNera@uvw.ru
`. `~’              GPGKey: 1024D / F8E26537 2006-11-21
  `- 1B23 D4F8 8EC0 D902 0555  E438 AB8C 00CF F8E2 6537

Attachment
On 15/03/11 08:22, Dmitry E. Oboukhov wrote:
>
> DI>  14 марта 2011 г. 17:20 пользователь Олекс й Василь в<leopard_ne@inbox.ru>
> DI>  написал:
>
> DI>  Есть такой запрос:
> DI>  Select * from foo where catalog_id IN(2,3,6,1,4,66,44,23,45)
>
> DI>  Возможно ли вывести результат в таком же порядке, как и условие в IN,
> DI>  тоесть первый елемент с  catalog_id == 2, второй - catalog_id == 3, третий
> DI>  - catalog_id == 6, четвертый - catalog_id == 1 и т.д.
>
> DI>  Данную задачу можно решить, заменив IN на JOIN, например:
>
> DI>  dmitigr=>
> DI>  SELECT foo.* FROM (VALUES(1),(2),(3),(4),(6)) AS foo(catalog_id)
> DI>  JOIN (SELECT id.val, row_number() over() FROM (VALUES(3),(2),(6),(1),(4)) AS
> DI>  id(val)) AS id
> DI>  ON (foo.catalog_id = id.val) ORDER BY row_number;
> DI>  catalog_id
> DI>  ------------
> DI>  3
> DI>  2
> DI>  6
> DI>  1
> DI>  4
>
>
> кстати unnest как-то даже покороче выглядит
>
> SELECT
>      foo.*
>
> FROM
>      unnest('{3,2,6,1,4}'::int[]) idt
>
> JOIN
>      foo ON catalog_id = idt
>

Если оптимизатор выберет hashjoin или mergejoin вместо nested loop
то порядок результатов в выдаче будет произволен. Лучше не использовать
такой подход.

PS: никакой запрос без order by не дает гарантированной сортировки. все
ухищрения чтобы без этого обойтись или работают не всегда или могут
перестать работать даже при смене минорной версии базы.

--
SY, Maxim Boguk