简体   繁体   中英

SQL JSON array sort

record in DB:

id     info
0     [{"name":"a", "time":"2017-9-25 17:20:21"},{"name":"b", "time":"2017-9-25 23:23:41"},{"name":"c", "time":"2017-9-25 12:56:78"}]

my goal is to sort json array column info base on time , like:

id     info
0     [{"name":"c", "time":"2017-9-25 12:56:78"},{"name":"a", "time":"2017-9-25 17:20:21"},{"name":"b", "time":"2017-9-25 23:23:41"},]

I use sparkSQL, having no clue

What I Suggest

Alternate Database Storage System

I would not recommend storing data in this manner. It simply makes your data less accessible and malleable as you are experiencing now. If you store your data like this:

id     name    time
0      a       2017-9-25 17:20:21
0      b       2017-9-25 23:23:41
0      c       2017-9-25 12:56:71
1      ...     ...

Then you can select the data in time order using the ORDER BY method at the end of a select query. For example:

SELECT name, time FROM table_name where id=0 ORDER BY time asc;

If you have more columns in this table that you did not show, you may need a another table to efficiently store the information, but the performance benefits of foreign keys and joins between these types of tables would outweigh having all the data in one table as inconvenient JSON arrays.

You can do this by converting the json array into a sql result set, extract the sorting column, and finally convert it back to a json array:

DECLARE @json NVARCHAR(MAX);
SET @json = '[
    {"name":"a", "time":"2017-09-25 17:20:21"},
    {"name":"b", "time":"2017-09-25 23:23:41"},
    {"name":"c", "time":"2017-09-25 12:56:59"}
    ]';

WITH T AS (
    SELECT [Value] AS array_element
        , TRY_CAST(JSON_VALUE(Value, 'strict $.time') AS DATETIME) AS sorting
    FROM OPENJSON(@json, 'strict $')
)
SELECT STRING_AGG(T.array_element, ',') WITHIN GROUP (ORDER BY sorting)
FROM T

Notice:

  • I changed the sample data slightly, due to invalid months and seconds.
  • The STRING_AGG() function is only available from SQL 2017/Azure SQL Database. For older versions, use the classic "FOR XML PATH" method, which I will leave as an exercise to the reader.

If you want to apply it to a full sql table, use CROSS APPLY as follows:

DECLARE @json NVARCHAR(MAX);
SET @json = '[
    {"name":"a", "time":"2017-09-25 17:20:21"},
    {"name":"b", "time":"2017-09-25 23:23:41"},
    {"name":"c", "time":"2017-9-25 12:56:59"}
    ]';

WITH dat AS (
    SELECT * FROM (VALUES (1,@json), (2,@json)) AS T(id, info)
)
, T AS (
    SELECT id, [Value] AS array_element
            , TRY_CAST(JSON_VALUE(Value, 'strict $.time') AS DATETIME) AS sorting
    FROM dat
    CROSS APPLY OPENJSON(info, 'strict $')
)
SELECT id
    , STRING_AGG(T.array_element, ',') WITHIN GROUP (ORDER BY sorting) AS info
FROM T
GROUP BY id

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM