Найти записи с идентификатором в массиве IDS и сохранить порядок записей, сопоставляемых с идентификаторами [duplicate]

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

Если компьютер работал в базе 10, 0.1 будет 1 x 10⁻¹, 0.2 будет 2 x 10⁻¹, а 0.3 будет 3 x 10⁻¹. Целочисленная математика проста и точна, поэтому добавление 0.1 + 0.2, очевидно, приведет к 0.3.

Компьютеры обычно не работают в базе 10, они работают в базе 2. Вы все равно можете получить точные результаты для некоторые значения, например 0.5, равны 1 x 2⁻¹, а 0.25 - 1 x 2⁻², а их добавление приводит к 3 x 2⁻² или 0.75. Точно.

Проблема связана с числами, которые могут быть представлены точно в базе 10, но не в базе 2. Эти цифры должны округляться до их ближайшего эквивалента. Предполагая, что для 64-битного формата с плавающей точкой IEEE используется очень общий формат, ближайшим номером к 0.1 является 3602879701896397 x 2⁻⁵⁵, а ближайшим номером к 0.2 является 7205759403792794 x 2⁻⁵⁵; добавление их результатов в 10808639105689191 x 2⁻⁵⁵ или точное десятичное значение 0.3000000000000000444089209850062616169452667236328125. Номера с плавающей запятой, как правило, округлены для отображения.

108
задан Erwin Brandstetter 5 March 2016 в 01:26
поделиться

13 ответов

С помощью Postgres 9.4 это можно сделать немного короче:

select c.*
from comments c
join (
  select *
  from unnest(array[43,47,42]) with ordinality
) as x (id, ordering) on c.id = x.id
order by x.ordering

Удаление необходимости вручную назначать / поддерживать позицию для каждого значения.

С помощью Postgres 9.6 это можно сделать, используя array_position():

with x (id_list) as (
  values (array[42,48,43])
)
select c.*
from comments c, x
where id = any (x.id_list)
order by array_position(x.id_list, c.id);

CTE используется, так что список значений должен быть только указанный один раз. Если это не важно, это также можно записать в виде:

select c.*
from comments c
where id in (42,48,43)
order by array_position(array[42,48,43], c.id);
20
ответ дан a_horse_with_no_name 26 August 2018 в 09:01
поделиться

В Postgresql:

select *
from comments
where id in (1,3,2,4)
order by position(id::text in '1,3,2,4')
16
ответ дан Clodoaldo Neto 26 August 2018 в 09:01
поделиться

В Postgres 9.4 или новее это, вероятно, простейшее и быстрое :

SELECT c.*
FROM   comments c
JOIN   unnest('{1,3,2,4}'::int[]) WITH ORDINALITY t(id, ord) USING (id)
ORDER  BY t.ord;
  • Используя новый WITH ORDINALITY что @a_horse уже упоминается .
  • Нам не нужен подзапрос, мы можем использовать функцию возвращаемого набора, такую ​​как таблица.
  • Строковый литерал

Подробное объяснение:

29
ответ дан Community 26 August 2018 в 09:01
поделиться
SELECT * FROM "comments" JOIN (
  SELECT 1 as "id",1 as "order" UNION ALL 
  SELECT 3,2 UNION ALL SELECT 2,3 UNION ALL SELECT 4,4
) j ON "comments"."id" = j."id" ORDER BY j.ORDER

, или если вы предпочитаете зло над добром:

SELECT * FROM "comments" WHERE ("comments"."id" IN (1,3,2,4))
ORDER BY POSITION(','+"comments"."id"+',' IN ',1,3,2,4,')
1
ответ дан Hafthor 26 August 2018 в 09:01
поделиться

Просто потому, что его так сложно найти, и его нужно распространять: в mySQL это можно сделать гораздо проще , но я не знаю, работает ли он в другом SQL.

SELECT * FROM `comments`
WHERE `comments`.`id` IN ('12','5','3','17')
ORDER BY FIELD(`comments`.`id`,'12','5','3','17')
57
ответ дан Menno 26 August 2018 в 09:01
поделиться
create sequence serial start 1;

select * from comments c
join (select unnest(ARRAY[1,3,2,4]) as id, nextval('serial') as id_sorter) x
on x.id = c.id
order by x.id_sorter;

drop sequence serial;

[EDIT]

unsest еще не встроен в 8.3, но вы можете создать его самостоятельно (красота любого *):

create function unnest(anyarray) returns setof anyelement
language sql as
$$
    select $1[i] from generate_series(array_lower($1,1),array_upper($1,1)) i;
$$;

эта функция может работать в любом типе:

select unnest(array['John','Paul','George','Ringo']) as beatle
select unnest(array[1,3,2,4]) as id
2
ответ дан Michael Buen 26 August 2018 в 09:01
поделиться

И вот другое решение, которое работает и использует постоянную таблицу ( http://www.postgresql.org/docs/8.3/interactive/sql-values.html ):

SELECT * FROM comments AS c,
(VALUES (1,1),(3,2),(2,3),(4,4) ) AS t (ord_id,ord)
WHERE (c.id IN (1,3,2,4)) AND (c.id = t.ord_id)
ORDER BY ord

Но опять же я не уверен, что это исполнитель.

Теперь у меня есть куча ответов. Могу ли я получить голосование и комментарии, чтобы я знал, кто победитель!

Спасибо всем :-)

3
ответ дан nutcracker 26 August 2018 в 09:01
поделиться

Чтобы сделать это, я думаю, что у вас, вероятно, должна быть дополнительная таблица «ORDER», которая определяет сопоставление идентификаторов на заказ (эффективно делая то, что ответ на ваш собственный вопрос), которые затем можно использовать в качестве дополнительного столбца на ваш выбор, который вы затем можете сортировать.

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

2
ответ дан Paul Sonier 26 August 2018 в 09:01
поделиться

Я думаю, что этот способ лучше:

SELECT * FROM "comments" WHERE ("comments"."id" IN (1,3,2,4))
    ORDER BY  id=1 DESC, id=3 DESC, id=2 DESC, id=4 DESC
36
ответ дан R4chi7 26 August 2018 в 09:01
поделиться

Другим способом сделать это в Postgres будет использование функции idx.

SELECT *
FROM comments
ORDER BY idx(array[1,3,2,4], comments.id)

Не забудьте сначала создать функцию idx, как описано здесь: http://wiki.postgresql.org/wiki/Array_Index

26
ответ дан That1Guy 26 August 2018 в 09:01
поделиться

Я согласен со всеми другими плакатами, которые говорят «не делай этого», или «SQL не хорош в этом». Если вы хотите отсортировать по некоторым аспектам комментариев, добавьте еще один целочисленный столбец в одну из ваших таблиц, чтобы сохранить критерии сортировки и отсортировать их по этому значению. например, «ORDER BY comments.sort DESC» Если вы хотите сортировать их в другом порядке каждый раз, тогда ... SQL не будет для вас в этом случае.

0
ответ дан Trey 26 August 2018 в 09:01
поделиться

Небольшое улучшение по сравнению с версией, которая использует последовательность, я думаю:

CREATE OR REPLACE FUNCTION in_sort(anyarray, out id anyelement, out ordinal int)
LANGUAGE SQL AS
$$
    SELECT $1[i], i FROM generate_series(array_lower($1,1),array_upper($1,1)) i;
$$;

SELECT 
    * 
FROM 
    comments c
    INNER JOIN (SELECT * FROM in_sort(ARRAY[1,3,2,4])) AS in_sort
        USING (id)
ORDER BY in_sort.ordinal;
0
ответ дан user 26 August 2018 в 09:01
поделиться
select * from comments where comments.id in 
(select unnest(ids) from bbs where id=19795) 
order by array_position((select ids from bbs where id=19795),comments.id)

здесь, [bbs] - основная таблица с полем, называемым ids, и, ids - это массив, в котором хранятся комментарии .id.

передано в postgresql 9.6

0
ответ дан user6161156 26 August 2018 в 09:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: