【问题标题】:Select row where nested JSON array contains certain value选择嵌套 JSON 数组包含特定值的行
【发布时间】:2020-06-18 09:11:19
【问题描述】:

我在Employee 表中有几个这样的数据库行:

EmpId       Name        Information
1           Eric       {“Experience”: [{“Title”: “Assistant Accountant”, “Company”: “ComA”, “YearsOfExperience”: 3}, {“Title”: “Accountant”, “Company”: “ComB”, “YearsOfExperience”: 2}], “EmployedYear”:2016}
2           John       {“Experience”: [{“Title”: “Tech Engineer”, “Company”: “ComX”, “Years”: 5}, {“Title”: “Senior Tech Engineer”, “Company”: “ComY”, “YearsOfExperience”: 2}], “EmployedYear”:2012}
3           Leonard    {“Experience”: [{“Title”: “Junior Engineer”, “Company”: “ComJ”, “Years”: 2}, {“Title”: “Tech Engineer”, “Company”: “ComB”, “YearsOfExperience”: “7”}], “EmployedYear”:2017}

我如何选择没有在 ComB 工作过的员工?

对此有什么查询?到目前为止,由于这个复杂的嵌套 JSON 数组,我一无所获。

我正在尝试:

SELECT Name, Id 
FROM Employee
OUTER APPLY OPENJSON(Information, '$.Experience') WITH (
   Title nvarchar(max) '$.Title', 
   Company nvarchar(max) '$.Company', 
   YearsOfExperience int '$.YearsOfExperience'
) AS [Info]
WHERE [Info].Company != 'ComB'

【问题讨论】:

  • 使用OPENJSON。这个 JSON 并不是特别复杂,所以至少我们为什么你所拥有的东西不起作用。
  • 仅供参考,您的 JSON 不使用风格化双引号(),因为某些解析将无法读取它们。使用非样式化双引号 (")。
  • EricLeonardComB有工作经验。你确定这个问题(我如何选择没有在 ComB 工作过的员工,在这种情况下他们是 Eric 和 Leonard?)?
  • 谢谢大家,解决了,我应该用Exist check

标签: sql json sql-server select sql-server-json


【解决方案1】:

您可以尝试使用EXISTS()OPENJSON()

表:

CREATE TABLE Employee (
    EmpId int,       
    Name varchar(100),        
    Information varchar(1000)
)
INSERT INTO Employee (EmpId, Name, Information)
VALUES
    (1, 'Eric',    '{"Experience":[{"Title":"Assistant Accountant","Company":"ComA","YearsOfExperience":3},{"Title":"Accountant","Company":"ComB","YearsOfExperience":2}],"EmployedYear":2016}'),
    (2, 'John',    '{"Experience":[{"Title":"Tech Engineer","Company":"ComX","Years":5},{"Title":"Senior Tech Engineer","Company":"ComY","YearsOfExperience":2}],"EmployedYear":2012}'),
    (3, 'Leonard', '{"Experience":[{"Title":"Junior Engineer","Company":"ComJ","Years":2},{"Title":"Tech Engineer","Company":"ComB","YearsOfExperience":"7"}],"EmployedYear":2017}')

声明:

SELECT Name, EmpId 
FROM Employee
WHERE NOT EXISTS (
   SELECT 1
   FROM OPENJSON(Information, '$.Experience') WITH (
     Title nvarchar(max) '$.Title', 
     Company nvarchar(max) '$.Company', 
     YearsOfExperience int '$.YearsOfExperience'
   ) AS [Info]
   WHERE [Info].Company = 'ComB'
)

【讨论】:

    【解决方案2】:

    一种方法是在HAVING 子句中进行一些条件聚合:

    SELECT V.EmpId,
           V.Name
    FROM (VALUES(1,'Eric',N'{"Experience": [{"Title": "Assistant Accountant", "Company": "ComA", "YearsOfExperience": 3}, {"Title": "Accountant", "Company": "ComB", "YearsOfExperience": 2}], "EmployedYear":2016}'),
                (2,'John',N'{"Experience": [{"Title": "Tech Engineer", "Company": "ComX", "Years": 5}, {"Title": "Senior Tech Engineer", "Company": "ComY", "YearsOfExperience": 2}], "EmployedYear":2012}'),
                (3,'Leonard',N'{"Experience": [{"Title": "Junior Engineer", "Company": "ComJ", "Years": 2}, {"Title": "Tech Engineer", "Company": "ComB", "YearsOfExperience": "7"}], "EmployedYear":2017}'))V(EmpId,[Name],Information)
         CROSS APPLY OPENJSON(Information,'$.Experience')
         WITH (Title nvarchar(50),
               Company nvarchar(50),
               Years int) OJ
    GROUP BY V.EmpId, V.Name
    HAVING COUNT(CASE OJ.Company WHEN 'ComB' THEN 1 END) = 0;
    

    【讨论】:

      【解决方案3】:

      您可以使用openjson() 和横向连接。您不需要从嵌套对象中提取所有属性,因为您只对公司名称感兴趣:

      select e.empId, e.Name
      from employee e
      where exists (
          select 1
          from openjson(information, '$.Experience') with(company nvarchar(max) '$.Company')
          where company = 'ComB'
      )
      

      Demo on DB Fiddle

      员工 |姓名 ----: | :------ 1 |埃里克 3 |伦纳德

      【讨论】:

        猜你喜欢
        • 2020-11-25
        • 2021-12-20
        • 2021-05-06
        • 1970-01-01
        • 2021-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-10
        相关资源
        最近更新 更多