Posgres: Упорядочить по :: timestamp asc и desc столбца jsonb, которые дают те же результаты, что и по последней отметке времени - PullRequest
0 голосов
/ 11 ноября 2018

У меня есть этот запрос, который извлекает 1 строку на основе UUID doc_id документов таблицы, который также имеет тип столбца поля jsonb:

select 
    DISTINCT ON (doc_id) 
    *
    FROM ( 
        select d.doc_id, c.comments 
        from documents as d 
        cross join lateral jsonb_array_elements(comments) 
        WITH ORDINALITY c(comments)
        WHERE (c.comments ->> 'isUser'):: boolean is false 
        order by (c.comments ->>'timestamp')::timestamp desc
    ) as s;

Когда я пытаюсь:

        order by (c.comments ->>'timestamp')::timestamp desc

Я получаю точно такой же результат. Я даже попробовал с timestamptz:

        order by (c.comments ->>'timestamp')::timestamptz asc

Пример содержимого столбца комментариев jsonb:

[...
{
    "text": "30",
    "timestamp": "2018-11-11T09:13:23.242Z", // older
    "isUser": false
},{
    "text": "31",
    "timestamp": "2018-11-11T12:53:48.620Z", // LATEST
    "isUser": false
}]

Как вы можете видеть, объект с текстом 30 старше, но он всегда возвращается в запросах выше.

1 Ответ

0 голосов
/ 11 ноября 2018

Порядок не имеет отношения к окончательному результату, потому что он применяется только к оператору SELECT, в котором он используется, то есть к вашему подзапросу. Затем вы выполняете другой запрос для этих результатов, используя DISTINCT ON, который будет выполнять любые вычисления и возвращать вам результаты в некотором порядке, но, вероятно, не тот, который вам нужен.

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

select 
    DISTINCT ON (doc_id) 
    doc_id, comments
    FROM ( 
        select d.doc_id, c.comments, (c.comments ->>'timestamp')::timestamp AS comment_timestamp
        from documents as d 
        cross join lateral jsonb_array_elements(comments) 
        WITH ORDINALITY c(comments)
        WHERE (c.comments ->> 'isUser'):: boolean is false 
    ) as s
ORDER BY doc_id, comment_timestamp DESC

Возможно, я что-то упускаю, но, похоже, вам все равно не нужен подзапрос, разве это не сработает?

select DISTINCT ON (d.doc_id) d.doc_id, c.comments 
from documents as d 
cross join lateral jsonb_array_elements(comments) 
WITH ORDINALITY c(comments)
WHERE (c.comments ->> 'isUser'):: boolean is false 
order by d.doc_id, (c.comments ->>'timestamp')::timestamp desc
...