MS SQL json query / where子句嵌套数组项

时间:2016-11-14 08:39:46

标签: sql sql-server json sql-server-2016

我有json数据,我可以查询使用" CROSS APPLY OPENJSON("一旦你开始添加多个交叉应用或一旦你的json文档变得太大就会变慢。所以我想添加一个我试图过滤的数据的索引,但我不能使用交叉应用得到嵌套数组项的语法。因此我不能创建一个索引,因为你不能使用交叉应用制作索引。我应该能够做的MS文档


    JSON_query(my_column, $.parentItem.nestedItemsArray1.nestedItemsArray2)

我应该能够获取嵌套的数组项的所有值然后查询并通过添加索引来提高性能,类似这样

    ALTER TABLE mytable 
    ADD vdata AS JSON_query(my_column, 
      $.parentItem.nestedItemsArray1.nestedItemsArray2')  

    CREATE INDEX idx_json_my_column ON mytable(vdata)

但上面的$ .array.arrayitems语法不起作用? 在旁注,我不能帮助,但在关系术语中思考通常在Sql中你会索引一列数据,如此

    col
    ---
     1| 
     2|
     3|

但是json数据似乎变得扁平,所以当我根据MS示例使用JSON_QUERY时,我得到" 1,2,3" "我假设我想索引一个值数组而不是一个扁平化的版本,除非索引将返回加肥数据的内部数据?

我的即插即用工作示例


    declare  @mydata table (    
      ID int NOT NULL,  
      jsondata varchar(max) NOT NULL  
    )

    INSERT INTO @mydata (id, jsondata)
        VALUES (789, '{ "Id": "12345", "FinanceProductResults": [ { "Term": 12, "AnnualMileage": 5000, "Deposits": 0, "ProductResults": [] }, { "Term": 18, "AnnualMileage": 30000, "Deposits": 15000, "ProductResults": [] }, { "Term": 24, "AnnualMileage": 5000, "Deposits": 0, "ProductResults": [ { "Key": "HP", "Payment": 460.28 } ] }, { "Term": 24, "AnnualMileage": 10000, "Deposits": 0, "ProductResults": [ { "Key": "HP", "Payment": 500.32 } ] }]}')

    SELECT 
        j_Id
        ,JSON_query (c.value, '$.Term') as Term
        ,JSON_Value (c.value, '$.AnnualMileage') as AnnualMileage
        ,JSON_Value (c.value, '$.Deposits') as Deposits     
        ,JSON_Value (p.value, '$.Key') as [Key]
        ,JSON_Value (p.value, '$.Payment') as Payment
        --,c.value
    FROM @mydata  f 
        CROSS APPLY OPENJSON(f.jsondata)
            WITH (j_Id nvarchar(100) '$.Id')
        CROSS APPLY OPENJSON(f.jsondata, '$.FinanceProductResults') AS c
        CROSS APPLY OPENJSON(c.value, '$."ProductResults"') AS p
    where 
        ID = 789 
        AND JSON_Value (p.value, '$.Payment') = '460.28'

我正在使用这些MS文档来指导我:

How to create an index

How to get data

更新

我能够使用""稍微提高性能。方法


    SELECT 
        j_Id,
        FinanceDetails.Term,
        FinanceDetails.AnnualMileage,
        FinanceDetails.Deposits,
        Payments.Payment
    FROM @mydata  f 
        CROSS APPLY OPENJSON(f.jsondata)
            WITH (j_Id nvarchar(100) '$.Id')
        OUTER APPLY OPENJSON (f.jsondata, '$.FinanceProductResults' )  
                WITH (   
                    Term            INT             '$.Term',  
                    AnnualMileage   INT             '$.AnnualMileage',  
                    Deposits        INT             '$.Deposits',  
                    ProductResults  NVARCHAR(MAX)   '$.ProductResults'  AS JSON  
                ) AS FinanceDetails
            OUTER APPLY OPENJSON(ProductResults,  '$') 
                WITH (   
                    Payment DECIMAL(19, 4)          '$.Payment' 
                ) AS Payments
    WHERE   
        Payments.Payment = 460.28

但我还是想在子阵列数据上添加索引以帮助提高性能?

1 个答案:

答案 0 :(得分:0)

目前,您无法索引嵌套属性。 是否可以选择全文搜索?您可以在JSON列上创建FTS并添加谓词:

public class QuestionElement
{   
    public IWebElement Element { get; set; }

}

public class QuestionItem
{
    public string QuestionID { get; set; }
    public list<QuestionElement> Elements;
}

public class QuestionItems
{
    public SortedList<QuestionItem> Questions { get; set; }
}

public class PopulateQuestionItem()
{


    public void AddQuestionResult(string questionID, QuestionItems questionItems, string colorItem)
    {
        IReadOnlyCollection<IWebElement> unfiltered = Driver.FindElements(By.CssSelector("*"));

        List<IWebElement> filtered = unfiltered.Where(f => f.GetCssValue("color") == colorItem).ToList();
        QuestionItem questionItem = new QuestionItem() { QuestionID = questionID };

        foreach (IWebElement element in filtered)
        {
            QuestionElement item = new QuestionElement()
            {
                Element = element

            };
            questionItem.ElementsAdd(item);
        }

        questionItems.Questions.Add(questionID, questionItem);

    }      

由于JSON是文本,因此该谓词将过滤掉所有不具有&#34;付款&#34;和460彼此靠近(这将识别键:值对),你可以在减少的行集上应用CROSS APPLY。