【问题标题】:SQL JSON array sortSQL JSON数组排序
【发布时间】:2018-03-10 21:46:35
【问题描述】:

在数据库中记录:

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"}]

我的目标是基于time 对json 数组列info 进行排序,例如:

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"},]

我用的是sparkSQL,不知道

【问题讨论】:

  • 是否可以只写一个程序,查询所有行,反序列化,在代码中重新排序,逐行更新?

标签: mysql sql arrays json apache-spark-sql


【解决方案1】:

可以通过将json数组转换为sql结果集,提取排序列,最后再转换回json数组:

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

注意:

  • 由于月份和秒数无效,我稍微更改了示例数据。
  • STRING_AGG() 函数仅适用于 SQL 2017/Azure SQL 数据库。对于旧版本,请使用经典的“FOR XML PATH”方法,我将把它作为练习留给读者。

如果要将其应用到完整的 sql 表,请使用 CROSS APPLY,如下所示:

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

【讨论】:

    【解决方案2】:

    我的建议

    备用数据库存储系统

    我不建议以这种方式存储数据。正如您现在所经历的那样,它只会使您的数据更难以访问和延展。如果您像这样存储数据:

    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      ...     ...
    

    然后您可以在选择查询结束时使用ORDER BY 方法按时间顺序选择数据。例如:

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

    如果您在此表中有更多未显示的列,您可能需要另一个表来有效地存储信息,但外键和这些类型表之间的连接的性能优势将超过将所有数据放入一张表作为不方便的 JSON 数组。

    【讨论】:

    • 如果解决方案这么简单,我这里就不问了,数据结构是不可改变的
    • @no123ff 表现出一点礼貌总是值得赞赏的 =)
    • @ChorWaiChun bling bling bling
    • @no123ff 我将尝试制作一个 MySQL 程序来解决您喜欢的数据结构。
    • @no123ff 我建议您通读wikipedia 上的一些公认的数据库规范。
    猜你喜欢
    • 2020-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    • 2017-08-12
    相关资源
    最近更新 更多