选择嵌套 JSON 数组包含特定值的行

Posted

技术标签:

【中文标题】选择嵌套 JSON 数组包含特定值的行【英文标题】:Select row where nested JSON array contains certain value 【发布时间】: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 【参考方案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 |伦纳德

【讨论】:

以上是关于选择嵌套 JSON 数组包含特定值的行的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 中选择具有唯一列值的行

Sequelize(或清除 SQL)查询以选择包含 JSON 字段中的值的行?

使用JQ从JSON中选择特定的,任意嵌套的对象

从 S3 读取大型 JSON 文件 (3K+) 并从数组中选择特定键

PostgreSQL 查询包含特定键值的 json 对象中的行

以特定方式在Excel中解析JSON嵌套数组