根据服务日期从 JSON 格式列中分配正确的负责人

Assign correct Responsible person from JSON format column based on Service Date

P.S。之前的post被删了,希望这次能更多人看到

我有庞大的历史数据集,我需要根据与客户关联的所有行的服务日期,将值(ResponsibleName - 来自 JSON 格式列)分配给新的 'Responsible' 列。

每个客户在特定日期范围内可以有唯一的负责人(JSON列):

  1. 如果代码列包含主管,则将此员工分配给仅关联行作为负责人。
  2. 最后,如果代码列包含员工,则将 JSON 列(针对特定日期范围)中的相关责任人分配给责任人

第一步我没有问题,但是我找不到实现第二个(最后一个)语句的解决方案。

原始历史记录Table加入客户Table:

SELECT h.Id,
       h.ServiceDate
       h.ClientId,
       cl.ClientName,
       h.EmployeeName,
       cl.ResponsibleJSON,
       h.Codes
FROM History AS h
JOIN ClientTable AS cl
   ON (h.ClientId = cl.ClientId)

table 的输出:

Id ServiceDate ClientId ClientName EmployeeName ResponsibleJSON Codes
1 2020-05-06 123 John Smith Chris Evans [{"ResponsibleName":"Kevin Costner","ResponsibleStartDate":"2019-02-14","ResponsibleEndDate":"2020-05-31"},{"ResponsibleName":"Tom Cruise", "ResponsibleStartDate":"2020-06-01","ResponsibleEndDate":null}] Employee, Office
2 2020-05-08 123 John Smith Tom Holland [{"ResponsibleName":"Kevin Costner","ResponsibleStartDate":"2019-02-14","ResponsibleEndDate":"2020-05-31"},{"ResponsibleName":"Tom Cruise", "ResponsibleStartDate":"2020-06-01","ResponsibleEndDate":null}] Supervisor, Remote
3 2020-05-11 123 John Smith Chris Evans [{"ResponsibleName":"Kevin Costner","ResponsibleStartDate":"2019-02-14","ResponsibleEndDate":"2020-05-31"},{"ResponsibleName":"Tom Cruise", "ResponsibleStartDate":"2020-06-01","ResponsibleEndDate":null}] Employee, Office
4 2020-05-15 123 John Smith Thomas Anderson [{"ResponsibleName":"Kevin Costner","ResponsibleStartDate":"2019-02-14","ResponsibleEndDate":"2020-05-31"},{"ResponsibleName":"Tom Cruise", "ResponsibleStartDate":"2020-06-01","ResponsibleEndDate":null}] Employee, Office
5 2020-06-10 123 John Smith Tom Holland [{"ResponsibleName":"Kevin Costner","ResponsibleStartDate":"2019-02-14","ResponsibleEndDate":"2020-05-31"},{"ResponsibleName":"Tom Cruise", "ResponsibleStartDate":"2020-06-01","ResponsibleEndDate":null}] Supervisor, Office
6 2020-06-17 123 John Smith Thomas Anderson [{"ResponsibleName":"Kevin Costner","ResponsibleStartDate":"2019-02-14","ResponsibleEndDate":"2020-05-31"},{"ResponsibleName":"Tom Cruise", "ResponsibleStartDate":"2020-06-01","ResponsibleEndDate":null}] Employee, Remote
7 2020-06-22 123 John Smith Elon Mask [{"ResponsibleName":"Kevin Costner","ResponsibleStartDate":"2019-02-14","ResponsibleEndDate":"2020-05-31"},{"ResponsibleName":"Tom Cruise", "ResponsibleStartDate":"2020-06-01","ResponsibleEndDate":null}] Employee, Remote
8 2020-07-01 123 John Smith Tom Holland [{"ResponsibleName":"Kevin Costner","ResponsibleStartDate":"2019-02-14","ResponsibleEndDate":"2020-05-31"},{"ResponsibleName":"Tom Cruise", "ResponsibleStartDate":"2020-06-01","ResponsibleEndDate":null}] Supervisor, Remote

我已经为所有客户创建了 table,其中包含所有 JSON 数据:

SELECT  c.ClientId,
        c.ClientFullName,
        c.ResponsibleJSON,
        JSON_VALUE(X.VALUE,'$.ResponsibleName') AS ResponsibleName,
        JSON_VALUE(X.VALUE,'$.ResponsibleStartDate') AS ResponsibleStartDate,
        ISNULL(JSON_VALUE(X.VALUE,'$.ResponsibleEndDate'), '2999-12-31') AS ResponsibleEndDate

FROM ClientTable AS c
CROSS APPLY OPENJSON(c.ResponsibleJSON) AS X
ORDER BY c.ClientFullName, ResponsibleStartDate

现在我需要以某种方式组合它们以生成下面的列:

期望的输出:

Responsible
Kevin Costner
Tom Holland
Kevin Costner
Kevin Costner
Tom Holland
Tom Cruise
Tom Cruise
Tom Holland

我需要帮助的代码可以在下面找到。 我不知道我是否可以在 CASE 语句中进行 OUTER APPLY 并且我认为 JOIN 应该在 ClientId 上并检查 ServiceDate 是否在 ResponsibleStartDate 和 ResponsibleEndDate 之间。

SELECT h.Id,
       h.ServiceDate
       h.ClientId,
       cl.ClientName,
       h.EmployeeName,
       cl.ResponsibleJSON,
       h.Codes,

       CASE
          WHEN h.Codes LIKE '%Supervisor%' THEN h.EmployeeName --- 1st statement
          WHEN --- here should be the second statement. I don't know how to implement it.
       END AS Responsible

FROM History AS h
JOIN ClientTable AS cl
   ON (h.ClientId = cl.ClientId)

Codes 列不包含 Supervisor 时,您似乎只想查找 JSON。以下查询应执行您想要的操作:

SELECT
  c.Id,
  c.ServiceDate,
  c.ClientId,
  c.ClientName,
  c.EmployeeName,
  c.Codes,
  Supervisor =
      CASE WHEN c.Codes LIKE '%Supervisor%' THEN c.EmployeeName
      ELSE (
          SELECT TOP (1)
            j.ResponsibleName
          FROM OPENJSON(c.ResponsibleJSON)
            WITH (
              ResponsibleName nvarchar(100),
              ResponsibleStartDate date,
              ResponsibleEndDate date
            ) j
          WHERE c.ServiceDate >= j.ResponsibleStartDate
            AND (j.ResponsibleEndDate IS NULL OR c.ServiceDate <= j.ResponsibleEndDate)
      )
      END
FROM ClientTable c;

db<>fiddle