使用FOR JSON

时间:2018-09-27 08:44:45

标签: sql json sql-server tsql for-json

我正在尝试展平由FOR JSON构造的对象数组。

我的查询如下:

select 
(                           
    select id from MyTable
    where id in (select value from OPENJSON(@jsonArray))
    FOR JSON PATH
) existing,                 
(   
    select value id from OPENJSON(@jsonArray) 
    where value not in (select Id from MyTable)
    FOR JSON PATH                       
) missing
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER

生成的JSON是:

{
    "existing": [
        {
            "id": "a00cd8f6-d1c6-4604-b235-59d3cacd5bcc"
        },
        {
            "id": "052455b6-6bf5-47d3-8bee-7ba98d7fbd50"
        }
    ],
    "missing": [
        {
            "id": "328add2d-e8f2-4a0e-af54-5b1733310170"
        }
    ]
}

我想要的是:

{
    "existing": [
        {
            "id": "a00cd8f6-d1c6-4604-b235-59d3cacd5bcc"
        },
        {
            "id": "052455b6-6bf5-47d3-8bee-7ba98d7fbd50"
        }
    ],
    "missing": [
        "328add2d-e8f2-4a0e-af54-5b1733310170"            
    ]
}

缺少的数组不应包含json对象,而应包含值。 有什么建议吗?

3 个答案:

答案 0 :(得分:1)

如果您使用的是SQL Server 2017,则可以使用JSON_QUERYSTRING_AGG构建数组(使用SQL Server 2016时,您不能使用STRING_AGG,因此必须有点estra的工作,但以下想法仍然有效):

declare @missing table(id varchar(max))
declare @existing table(id varchar(max))

insert into @missing values ('a00cd8f6-d1c6-4604-b235-59d3cacd5bcc')
insert into @missing values ('052455b6-6bf5-47d3-8bee-7ba98d7fbd50')
insert into @existing values ('328add2d-e8f2-4a0e-af54-5b1733310170')

select  
(                           
    select id from @missing
    FOR JSON PATH
) existing,                
(   
    select JSON_QUERY(concat('[' , STRING_AGG(concat('"' , STRING_ESCAPE(id, 'json') , '"'),',') , ']')) 
    from @existing                 
) missing 
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER

结果:

{
  "existing": [
    {
      "id": "a00cd8f6-d1c6-4604-b235-59d3cacd5bcc"
    },
    {
      "id": "052455b6-6bf5-47d3-8bee-7ba98d7fbd50"
    }
  ],
  "missing": [
    "328add2d-e8f2-4a0e-af54-5b1733310170"
  ]
}

答案 1 :(得分:0)

这并不像应该做的那么简单...

AFAIK无法使用sql-server创建 json数组。但是您可以在字符串级别上欺骗它:

SELECT SUM(meta_value) FROM `order_itemmeta` im2 
WHERE meta_key = '_qty' AND 
im2.order_item_id IN (
  SELECT im.order_item_id
  FROM `order_itemmeta` im  
  RIGHT JOIN `order_items` i ON im.order_item_id = i.order_item_id 
  WHERE im.meta_value = "' . $todays_date . '"
);

-这将创建所需的对象数组

DECLARE @exist TABLE(id VARCHAR(100));
DECLARE @miss TABLE(id VARCHAR(100));

INSERT INTO @exist VALUES ('exist1'),('exist2');
INSERT INTO @miss VALUES ('miss1'),('miss2');

-这将使用一些相当丑陋的技巧创建 naked 数组。

SELECT id FROM @exist
FOR JSON PATH

-现在我们必须将两者结合起来。再一次,我们需要一个技巧。我们在JSON文字上使用SELECT REPLACE(REPLACE(REPLACE( ( SELECT id from @miss FOR JSON PATH ),'"id":',''),'{',''),'}','') 以避免转义引号。

JSON_QUERY()

这就是结果

SELECT
(
    SELECT id FROM @exist
    FOR JSON PATH
) AS existing
,JSON_QUERY(
   REPLACE(REPLACE(REPLACE(
    (
        SELECT id from @miss
        FOR JSON PATH
    ),'"id":',''),'{',''),'}','')
) AS missing
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;

我不知道为什么为什么不能做到这一点开箱即用 ...

答案 2 :(得分:0)

使用游标追加

DECLARE @missing nvarchar(max),
    @json nvarchar(max) = (select 
                            (                           
                                select id from MyTable
                                where id in (select value from OPENJSON(@jsonArray))
                                FOR JSON PATH
                            ) existing
                            FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)

    DECLARE missing_cursor CURSOR FOR   
        select value id 
        from OPENJSON(@jsonArray)
        where value not in (select Id from MyTable)

        OPEN missing_cursor  

        FETCH NEXT FROM missing_cursor   
        INTO @missing

        WHILE @@FETCH_STATUS = 0  
        BEGIN  
            SET @json = JSON_MODIFY(@json,'append $.missing', @missing)

            FETCH NEXT FROM missing_cursor   
            INTO @missing  
        END   
        CLOSE missing_cursor;  
        DEALLOCATE missing_cursor; 

    select @json