4

I have a few database rows like this in the Employee table:

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}

How do I select employees who have not worked in ComB?

What would be query for this? So far I got nothing because of this complex nested JSON array.

I'm trying now:

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'
Zhorov
  • 28,486
  • 6
  • 27
  • 52
april
  • 89
  • 1
  • 12
  • Use `OPENJSON`. This JSON isn't particularly complex, so at least so us why what you have isn't working. – Thom A Jun 18 '20 at 09:15
  • 1
    FYI, doesn't used stylised double quotes (`“` and `”`) for your JSON, as some parses won't be able to read them. Use unstylised double quotes (`"`). – Thom A Jun 18 '20 at 09:26
  • `Eric` and `Leonard` have working experience in `ComB`. Are you sure about the question (_How do I select employees who have not worked in ComB, in this case they're Eric and Leonard?_)? – Zhorov Jun 18 '20 at 09:32
  • Thanks everyone, solved it, I should have used Exist check – april Jun 18 '20 at 09:38

3 Answers3

3

You may try to use EXISTS() and OPENJSON().

Table:

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}')

Statement:

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'
)
Zhorov
  • 28,486
  • 6
  • 27
  • 52
0

One method is with some conditional aggregation in a HAVING clause`:

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;
Thom A
  • 88,727
  • 11
  • 45
  • 75
0

You can use openjson() and a lateral join. You don't need to extract all attributes from the nested objects, since you are only intersted in the company name:

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:

empId | Name   
----: | :------
    1 | Eric   
    3 | Leonard
GMB
  • 216,147
  • 25
  • 84
  • 135