PostgreSql Queries обрабатывает Int как строковые типы данных

Я храню следующие строки в своей таблице («DataScreen») в столбце JSONB («Результаты»)

{"Id":11,"Product":"Google Chrome","Handle":3091,"Description":"Google Chrome"}
{"Id":111,"Product":"Microsoft Sql","Handle":3092,"Description":"Microsoft Sql"}
{"Id":22,"Product":"Microsoft OneNote","Handle":3093,"Description":"Microsoft OneNote"}
{"Id":222,"Product":"Microsoft OneDrive","Handle":3094,"Description":"Microsoft OneDrive"}

Здесь в этих объектах JSON «Id» и «Handle» являются целочисленными свойствами, а другие — строковыми свойствами.

Когда я запрашиваю свою таблицу, как показано ниже

Select Results->>'Id'  From DataScreen  
order by Results->>'Id' ASC

Я получаю неправильные результаты, потому что PostgreSql обрабатывает все как текстовый столбец и, следовательно, упорядочивает в соответствии с текстом, а не как целое число. Следовательно, это дает результат как

11,111,22,222 

вместо

11,22,111,222.

Я не хочу использовать явное приведение для извлечения, как показано ниже.

Select Results->>'Id'  From DataScreen order by CAST(Results->>'Id' AS INT)  ASC

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

Я хочу что-то, чтобы целые числа в структуре Json столбца JSONB обрабатывались только как целые числа, а не как тексты (строки).

Как мне написать свой запрос, чтобы Id и Handle извлекались как целые значения, а не как строки, без явного приведения?


person puneet    schedule 25.02.2017    source источник
comment
Что ж, в JSON все является текстом. Кастинг является единственным вариантом. Если вам нужны строго типизированные столбцы, нормализуйте и не используйте JSON.   -  person a_horse_with_no_name    schedule 25.02.2017


Ответы (2)


Я думаю, что ваши предположения о поле id не имеют смысла. Вы сказали,

(a) Либо id содержит только целые числа, либо

(b) он содержит строки и целые числа.

Я бы сказал,

Если (а), то нумерация правильная.

Если (b), то лексический порядок правильный.

Но если (а) некоторое время, а затем (б), то и правильный порядок меняется. И это не имеет смысла. Представить:

Для текущей базы данных вы ожидаете порядок 11,22,111,222. Затем вы добавляете строку

{"Id":"aa","Product":"Microsoft OneDrive","Handle":3095,"Description":"Microsoft OneDrive"}

и вдруг правильный порядок других строк меняется на 11,111,22,222,aa. That меня беспокоят внезапные перемены.

Поэтому я бы либо ожидал лексического упорядочения ab intio, либо ограничил бы мое поле id целыми числами и использовал явное приведение.

Любой другой вариант, который я могу придумать, просто непрактичен. Например, вы можете создать пользовательскую реализацию < и > для поля id, в результате чего получится 11,111,22,222,aa. (Упорядочить все целые числа по числовому значению и все строки по лексическому порядку и поставить все целые числа перед строками).

Но это большая работа (она включает в себя пользовательский тип данных, пользовательскую функцию приведения и пользовательскую функцию оператора) и приводит к некоторым нелогичным результатам, например. 11,111,22,222,0a,1a,2a,aa (обратите внимание на положение 0a и т. д. Они идут после 222).

Надеюсь, это поможет ;)

person nCessity    schedule 25.02.2017
comment
Нет, поле Id всегда содержит целые числа, а не буквенно-цифровые. - person puneet; 26.02.2017
comment
Вы сказали: я не буду уверен в типе данных столбца из-за того, что структура JSON будет динамической, а ключи и значения могут измениться в следующий раз. и, следовательно, может произойти то же самое с другим JSON, имеющим целочисленные и строковые ключи. - person nCessity; 26.02.2017
comment
Да, я имел в виду, что вывод JSON больше не может быть одним и тем же набором ключей и значений. Это может быть другой набор пар ключа и значения JSON. Но если это ключи Id или Handle (и могут быть и другие), это должны быть целые числа. Точно так же может быть много наборов ключей, которые имеют целочисленные значения. Но я не хочу приводить его явно, потому что я не уверен, какой вывод JSON будет произведен в следующий раз, и какие все ключи будут целыми числами, а какие нет. - person puneet; 26.02.2017
comment
@puneet: если вы уверены, что Id всегда содержит целые числа, то почему не приводится вариант? - person a_horse_with_no_name; 27.02.2017

Если Id всегда целое, вы можете указать его в выбранной части и просто использовать ORDER BY 1:

select (Results->>'Id')::int  From DataScreen order by 1  ASC
person Roman Tkachuk    schedule 27.02.2017