将 T-SQL 格式化为 return JSON

Formating T-SQL to return JSON

我想使用 MS SQL 服务器将我的数据 return 作为 JSON 并且格式几乎正确,但我被卡住了。我想我需要另一个子查询,但我似乎无法让子查询正确格式化。

我一直在使用这个博客 post 作为我的 'tutorial' (XML_JSON),这对我到达那里很有帮助。如您所见,当您 运行 我的查询时,输出接近所需格式,但我没有正确嵌套 'Measure',我认为我需要另一个子查询才能使其正确。但是,我不清楚如何进行嵌套...

谢谢!!

DECLARE  @tmp_nata TABLE


(FIPS varchar(max),
   Measure VARCHAR(max),
   HAP VARCHAR(max),
   Result float)


INSERT INTO @tmp_nata
  (FIPS, Measure, HAP, Result)
VALUES
  ('00001', 'EnvConcEstimate', 'Benzene', 10.00),
  ('00001', 'EnvConcEstimate', 'Lead', 125.00),
  ('00001', 'EnvConcEstimate', 'Butadiene', 15.00),
  ('00001', 'EnvConcEstimate', 'Acrolein', 10.00),
  ('00001', 'EnvConcEstimate', 'Naphthalene', 15.00),
  ('00001', 'EnvConcEstimate', 'Formaldehyde', 10.00),
  ('00001', 'EnvConcEstimate', 'PAH', 125.00),
  ('00001', 'EnvConcEstimate', 'Acetaldehyde', 15.00),
  ('00001', 'EnvConcEstimate', 'Arsenic', 10.00),
  ('00001', 'EnvConcEstimate', 'Chromium', 15.00),
  ('00001', 'EnvConcEstimate', 'Diesel PM', 10.00),

  ('00001', 'NeuroNonCancer_HQ', 'Lead', 125.00),
  ('00001', 'Cum_AirToxicNonCancerNeuro', 'None', 15.00),
  ('00001', 'Cum_AirToxicNonCancerRespir', 'None', 10.00),
  ('00001', 'Cum_AirToxicCancer', 'None', 15.00),

  ('00001', 'RespNonCancer_HQ', 'Acrolein', 10.00),
  ('00001', 'RespNonCancer_HQ', 'Formaldehyde', 125.00),
  ('00001', 'RespNonCancer_HQ', 'Acetaldehyde', 15.00),
  ('00001', 'RespNonCancer_HQ', 'Diesel PM', 10.00),
  ('00001', 'RespNonCancer_HQ', 'Chromium', 15.00),
  ('00001', 'RespNonCancer_HQ', 'Naphthalene', 10.00),

  ('00001', 'HealthRiskEstimate', 'Benzene', 125.00),
  ('00001', 'HealthRiskEstimate', 'Butadiene', 15.00),
  ('00001', 'HealthRiskEstimate', 'Formaldehyde', 10.00),
  ('00001', 'HealthRiskEstimate', 'PAH', 15.00),
  ('00001', 'HealthRiskEstimate', 'Acetaldehyde', 10.00),
  ('00001', 'HealthRiskEstimate', 'Arsenic', 125.00),
  ('00001', 'HealthRiskEstimate', 'Chromium', 125.00),
  ('00001', 'HealthRiskEstimate', 'Naphthalene', 15.00),

  ('00001', 'HumanExpEstimate', 'Benzene', 10.00),
  ('00001', 'HumanExpEstimate', 'Lead', 125.00),
  ('00001', 'HumanExpEstimate', 'Butadiene', 15.00),
  ('00001', 'HumanExpEstimate', 'Acrolein', 10.00),
  ('00001', 'HumanExpEstimate', 'Naphthalene', 15.00),
  ('00001', 'HumanExpEstimate', 'Formaldehyde', 10.00),
  ('00001', 'HumanExpEstimate', 'PAH', 125.00),
  ('00001', 'HumanExpEstimate', 'Acetaldehyde', 15.00),
  ('00001', 'HumanExpEstimate', 'Arsenic', 10.00),
  ('00001', 'HumanExpEstimate', 'Chromium', 15.00),
  ('00001', 'HumanExpEstimate', 'Diesel PM', 10.00),

  ('20000', 'EnvConcEstimate', 'Benzene', 210.00),
  ('20000', 'EnvConcEstimate', 'Lead', 2125.00),
  ('20000', 'EnvConcEstimate', 'Butadiene', 215.00),
  ('20000', 'EnvConcEstimate', 'Acrolein', 250.00),
  ('20000', 'EnvConcEstimate', 'Naphthalene', 275.00),
  ('20000', 'EnvConcEstimate', 'Formaldehyde', 210.00),
  ('20000', 'EnvConcEstimate', 'PAH', 2125.00),
  ('20000', 'EnvConcEstimate', 'Acetaldehyde', 215.00),
  ('20000', 'EnvConcEstimate', 'Arsenic', 250.00),
  ('20000', 'EnvConcEstimate', 'Chromium', 275.00),
  ('20000', 'EnvConcEstimate', 'Diesel PM', 210.00),
  ('20000', 'NeuroNonCancer_HQ', 'Lead', 2125.00),
  ('20000', 'Cum_AirToxicNonCancerNeuro', 'None', 215.00),
  ('20000', 'Cum_AirToxicNonCancerRespir', 'None', 250.00),
  ('20000', 'Cum_AirToxicCancer', 'None', 275.00),

  ('20000', 'RespNonCancer_HQ', 'Acrolein', 210.00),
  ('20000', 'RespNonCancer_HQ', 'Formaldehyde', 2125.00),
  ('20000', 'RespNonCancer_HQ', 'Acetaldehyde', 215.00),
  ('20000', 'RespNonCancer_HQ', 'Diesel PM', 250.00),
  ('20000', 'RespNonCancer_HQ', 'Chromium', 75.00),
  ('20000', 'RespNonCancer_HQ', 'Naphthalene', 210.00),

  ('20000', 'HealthRiskEstimate', 'Benzene', 2125.00),
  ('20000', 'HealthRiskEstimate', 'Butadiene', 215.00),
  ('20000', 'HealthRiskEstimate', 'Formaldehyde', 250.00),
  ('20000', 'HealthRiskEstimate', 'PAH', 275.00),
  ('20000', 'HealthRiskEstimate', 'Acetaldehyde', 210.00),
  ('20000', 'HealthRiskEstimate', 'Arsenic', 2125.00),
  ('20000', 'HealthRiskEstimate', 'Chromium', 2125.00),
  ('20000', 'HealthRiskEstimate', 'Naphthalene', 215.00),

  ('20000', 'HumanExpEstimate', 'Benzene', 210.00),
  ('20000', 'HumanExpEstimate', 'Lead', 2125.00),
  ('20000', 'HumanExpEstimate', 'Butadiene', 215.00),
  ('20000', 'HumanExpEstimate', 'Acrolein', 250.00),
  ('20000', 'HumanExpEstimate', 'Naphthalene', 275.00),
  ('20000', 'HumanExpEstimate', 'Formaldehyde', 210.00),
  ('20000', 'HumanExpEstimate', 'PAH', 2125.00),
  ('20000', 'HumanExpEstimate', 'Acetaldehyde', 215.00),
  ('20000', 'HumanExpEstimate', 'Arsenic', 250.00),
  ('20000', 'HumanExpEstimate', 'Chromium', 275.00),
  ('20000', 'HumanExpEstimate', 'Diesel PM', 210.00) 

SELECT * from @tmp_nata

  SELECT
  FIPS, 
    STUFF((SELECT
          (',"' + SUB.Measure + '":{"'+ SUB.HAP+ '":' + CAST(Result as varchar(max)) + '}')
           FROM @tmp_nata SUB
           WHERE SUB.FIPS = AT.FIPS
           ORDER BY SUB.FIPS, SUB.Measure, SUB.HAP ASC
           FOR XML PATH('')
           ), 1, 1, '')  AS JSON
FROM @tmp_nata AT
WHERE 1 = 1
GROUP BY FIPS

所需的输出是每个 FIPS 一个 JSON,对于 FIPS=00001 看起来像这样:

{
    "EnvConcEstimate": {
        "Benzene": 10,
        "Lead": 125,
        "Butadiene": 15,
        "Acrolein": 10,
        "Naphthalene": 15,
        "Formaldehyde": 10,
        "PAH": 125,
        "Acetaldehyde": 15,
        "Arsenic": 10,
        "Chromium": 15,
        "Diesel PM": 10
    },
    "NeuroNonCancer_HQ": {
        "Lead": 125
    },
    "Cum_AirToxicNonCancerNeuro": {
        "None": 15
    },
    "Cum_AirToxicNonCancerRespir": {
        "None": 10
    },
    "Cum_AirToxicCancer": {
        "None": 15
    },
    "RespNonCancer_HQ": {
        "Acrolein": 10,
        "Formaldehyde": 125,
        "Acetaldehyde": 15,
        "Diesel PM": 10,
        "Chromium": 15,
        "Naphthalene": 10
    },
    "HealthRiskEstimate": {
        "Benzene": 125,
        "Butadiene": 15,
        "Formaldehyde": 10,
        "PAH": 15,
        "Acetaldehyde": 10,
        "Arsenic": 125,
        "Chromium": 125,
        "Naphthalene": 15
    },
    "HumanExpEstimate": {
        "Benzene": 10,
        "Lead": 125,
        "Butadiene": 15,
        "Acrolein": 10,
        "Naphthalene": 15,
        "Formaldehyde": 10,
        "PAH": 125,
        "Acetaldehyde": 15,
        "Arsenic": 10,
        "Chromium": 15,
        "Diesel PM": 10
    }
}

刚刚解决了你的问题,我在没有使用 FOR XML PATH 的情况下尝试了它,我所做的是为每行创建另一个 table 变量 with an extra field to build jason object ,我从 main table 插入到声明的 table,然后通过检查 PIPSMeasure 为每一行构建 json 对象。任何人都可以执行以下代码并检查结果 HERE


架构:

CREATE TABLE tmp_nata TABLE
(FIPS varchar(max),
   Measure VARCHAR(max),
   HAP VARCHAR(max),
   Result float)


INSERT INTO @tmp_nata
  (FIPS, Measure, HAP, Result)
VALUES
  ('00001', 'EnvConcEstimate', 'Benzene', 10.00),
  ('00001', 'EnvConcEstimate', 'Lead', 125.00),
  ('00001', 'EnvConcEstimate', 'Butadiene', 15.00),
  ('00001', 'EnvConcEstimate', 'Acrolein', 10.00),
  ('00001', 'EnvConcEstimate', 'Naphthalene', 15.00),
  ('00001', 'EnvConcEstimate', 'Formaldehyde', 10.00),
  ('00001', 'EnvConcEstimate', 'PAH', 125.00),
  ('00001', 'EnvConcEstimate', 'Acetaldehyde', 15.00),
  ('00001', 'EnvConcEstimate', 'Arsenic', 10.00),
  ('00001', 'EnvConcEstimate', 'Chromium', 15.00),
  ('00001', 'EnvConcEstimate', 'Diesel PM', 10.00),

  ('00001', 'NeuroNonCancer_HQ', 'Lead', 125.00),
  ('00001', 'Cum_AirToxicNonCancerNeuro', 'None', 15.00),
  ('00001', 'Cum_AirToxicNonCancerRespir', 'None', 10.00),
  ('00001', 'Cum_AirToxicCancer', 'None', 15.00),

  ('00001', 'RespNonCancer_HQ', 'Acrolein', 10.00),
  ('00001', 'RespNonCancer_HQ', 'Formaldehyde', 125.00),
  ('00001', 'RespNonCancer_HQ', 'Acetaldehyde', 15.00),
  ('00001', 'RespNonCancer_HQ', 'Diesel PM', 10.00),
  ('00001', 'RespNonCancer_HQ', 'Chromium', 15.00),
  ('00001', 'RespNonCancer_HQ', 'Naphthalene', 10.00),

  ('00001', 'HealthRiskEstimate', 'Benzene', 125.00),
  ('00001', 'HealthRiskEstimate', 'Butadiene', 15.00),
  ('00001', 'HealthRiskEstimate', 'Formaldehyde', 10.00),
  ('00001', 'HealthRiskEstimate', 'PAH', 15.00),
  ('00001', 'HealthRiskEstimate', 'Acetaldehyde', 10.00),
  ('00001', 'HealthRiskEstimate', 'Arsenic', 125.00),
  ('00001', 'HealthRiskEstimate', 'Chromium', 125.00),
  ('00001', 'HealthRiskEstimate', 'Naphthalene', 15.00),

  ('00001', 'HumanExpEstimate', 'Benzene', 10.00),
  ('00001', 'HumanExpEstimate', 'Lead', 125.00),
  ('00001', 'HumanExpEstimate', 'Butadiene', 15.00),
  ('00001', 'HumanExpEstimate', 'Acrolein', 10.00),
  ('00001', 'HumanExpEstimate', 'Naphthalene', 15.00),
  ('00001', 'HumanExpEstimate', 'Formaldehyde', 10.00),
  ('00001', 'HumanExpEstimate', 'PAH', 125.00),
  ('00001', 'HumanExpEstimate', 'Acetaldehyde', 15.00),
  ('00001', 'HumanExpEstimate', 'Arsenic', 10.00),
  ('00001', 'HumanExpEstimate', 'Chromium', 15.00),
  ('00001', 'HumanExpEstimate', 'Diesel PM', 10.00),

  ('20000', 'EnvConcEstimate', 'Benzene', 210.00),
  ('20000', 'EnvConcEstimate', 'Lead', 2125.00),
  ('20000', 'EnvConcEstimate', 'Butadiene', 215.00),
  ('20000', 'EnvConcEstimate', 'Acrolein', 250.00),
  ('20000', 'EnvConcEstimate', 'Naphthalene', 275.00),
  ('20000', 'EnvConcEstimate', 'Formaldehyde', 210.00),
  ('20000', 'EnvConcEstimate', 'PAH', 2125.00),
  ('20000', 'EnvConcEstimate', 'Acetaldehyde', 215.00),
  ('20000', 'EnvConcEstimate', 'Arsenic', 250.00),
  ('20000', 'EnvConcEstimate', 'Chromium', 275.00),
  ('20000', 'EnvConcEstimate', 'Diesel PM', 210.00),
  ('20000', 'NeuroNonCancer_HQ', 'Lead', 2125.00),
  ('20000', 'Cum_AirToxicNonCancerNeuro', 'None', 215.00),
  ('20000', 'Cum_AirToxicNonCancerRespir', 'None', 250.00),
  ('20000', 'Cum_AirToxicCancer', 'None', 275.00),

  ('20000', 'RespNonCancer_HQ', 'Acrolein', 210.00),
  ('20000', 'RespNonCancer_HQ', 'Formaldehyde', 2125.00),
  ('20000', 'RespNonCancer_HQ', 'Acetaldehyde', 215.00),
  ('20000', 'RespNonCancer_HQ', 'Diesel PM', 250.00),
  ('20000', 'RespNonCancer_HQ', 'Chromium', 75.00),
  ('20000', 'RespNonCancer_HQ', 'Naphthalene', 210.00),

  ('20000', 'HealthRiskEstimate', 'Benzene', 2125.00),
  ('20000', 'HealthRiskEstimate', 'Butadiene', 215.00),
  ('20000', 'HealthRiskEstimate', 'Formaldehyde', 250.00),
  ('20000', 'HealthRiskEstimate', 'PAH', 275.00),
  ('20000', 'HealthRiskEstimate', 'Acetaldehyde', 210.00),
  ('20000', 'HealthRiskEstimate', 'Arsenic', 2125.00),
  ('20000', 'HealthRiskEstimate', 'Chromium', 2125.00),
  ('20000', 'HealthRiskEstimate', 'Naphthalene', 215.00),

  ('20000', 'HumanExpEstimate', 'Benzene', 210.00),
  ('20000', 'HumanExpEstimate', 'Lead', 2125.00),
  ('20000', 'HumanExpEstimate', 'Butadiene', 215.00),
  ('20000', 'HumanExpEstimate', 'Acrolein', 250.00),
  ('20000', 'HumanExpEstimate', 'Naphthalene', 275.00),
  ('20000', 'HumanExpEstimate', 'Formaldehyde', 210.00),
  ('20000', 'HumanExpEstimate', 'PAH', 2125.00),
  ('20000', 'HumanExpEstimate', 'Acetaldehyde', 215.00),
  ('20000', 'HumanExpEstimate', 'Arsenic', 250.00),
  ('20000', 'HumanExpEstimate', 'Chromium', 275.00),
  ('20000', 'HumanExpEstimate', 'Diesel PM', 210.00) 

查询:

DECLARE
    @FIPS VARCHAR(50),
    @Measure VARCHAR(50),
    @Vals VARCHAR(MAX);

SET @FIPS ='';
SET @Measure ='';
SET @Vals ='';

DECLARE @t TABLE
(
    FIPS VARCHAR(50),
    Measure VARCHAR(50),
    HAP VARCHAR(50),
    Result FLOAT,
    Vals VARCHAR(MAX)
 ); 

INSERT @t(FIPS,Measure,HAP,Result)
SELECT FIPS,Measure,HAP,Result FROM tmp_nata
ORDER BY FIPS,Measure,HAP;


UPDATE @t 
SET @Vals = Vals =
    CASE @FIPS
         WHEN FIPS THEN
                   CASE @Measure
                        WHEN Measure THEN 
                                     @Vals +', "'+ HAP + '":'+cast(Result as varchar(100))
                        ELSE @Vals +'}, "'+Measure+'": {"'+ HAP + '":'+cast(Result as varchar(100))
                   END
         ELSE  '{ "'+Measure+'": {'+' "'+ HAP + '":'+cast(Result as varchar(100))
         END,
    @FIPS=FIPS, 
    @Measure = Measure;



SELECT DISTINCT FIPS, Vals= MAX(Vals)+'}}'
FROM @t
GROUP BY FIPS
ORDER BY FIPS;

输出:

FIPS    Vals
00001   { "EnvConcEstimate": { "Benzene":10, "Lead":125, "Butadiene":15, "Acrolein":10, "Naphthalene":15, "Formaldehyde":10, "PAH":125, "Acetaldehyde":15, "Arsenic":10, "Chromium":15, "Diesel PM":10}, "NeuroNonCancer_HQ": {"Lead":125}, "Cum_AirToxicNonCancerNeuro": {"None":15}, "Cum_AirToxicNonCancerRespir": {"None":10}, "Cum_AirToxicCancer": {"None":15}, "RespNonCancer_HQ": {"Acrolein":10, "Formaldehyde":125, "Acetaldehyde":15, "Diesel PM":10, "Chromium":15, "Naphthalene":10}, "HealthRiskEstimate": {"Benzene":125, "Butadiene":15, "Formaldehyde":10, "PAH":15, "Acetaldehyde":10, "Arsenic":125, "Chromium":125, "Naphthalene":15}, "HumanExpEstimate": {"Benzene":10, "Lead":125, "Butadiene":15, "Acrolein":10, "Naphthalene":15, "Formaldehyde":10, "PAH":125, "Acetaldehyde":15, "Arsenic":10, "Chromium":15, "Diesel PM":10}}
20000   { "EnvConcEstimate": { "Benzene":210, "Lead":2125, "Butadiene":215, "Acrolein":250, "Naphthalene":275, "Formaldehyde":210, "PAH":2125, "Acetaldehyde":215, "Arsenic":250, "Chromium":275, "Diesel PM":210}, "NeuroNonCancer_HQ": {"Lead":2125}, "Cum_AirToxicNonCancerNeuro": {"None":215}, "Cum_AirToxicNonCancerRespir": {"None":250}, "Cum_AirToxicCancer": {"None":275}, "RespNonCancer_HQ": {"Acrolein":210, "Formaldehyde":2125, "Acetaldehyde":215, "Diesel PM":250, "Chromium":75, "Naphthalene":210}, "HealthRiskEstimate": {"Benzene":2125, "Butadiene":215, "Formaldehyde":250, "PAH":275, "Acetaldehyde":210, "Arsenic":2125, "Chromium":2125, "Naphthalene":215}, "HumanExpEstimate": {"Benzene":210, "Lead":2125, "Butadiene":215, "Acrolein":250, "Naphthalene":275, "Formaldehyde":210, "PAH":2125, "Acetaldehyde":215, "Arsenic":250, "Chromium":275, "Diesel PM":210}}

您需要应用您的逻辑两次,首先是概率和结果,然后是衡量。您可以通过 CTE 来完成,例如:

;WITH cte AS(
SELECT
  FIPS, '"' + Measure +'":{'+
    STUFF((SELECT
          (',"' + SUB.HAP + '":'+CAST(Result AS VARCHAR(MAX)) + '')
           FROM t SUB
           WHERE SUB.FIPS = AT.FIPS AND SUB.Measure = AT.Measure
           ORDER BY SUB.Measure, SUB.HAP
           FOR XML PATH('')
           ), 1, 1, '') + '}' AS JSON
FROM t AT
GROUP BY FIPS, Measure)

SELECT FIPS, 
'{' + STUFF((SELECT
          (',' + JSON)
           FROM cte SUB
           WHERE SUB.FIPS = AT.FIPS
           ORDER BY SUB.FIPS
           FOR XML PATH('')
           ), 1, 1, '') + '}' AS JSON
           FROM cte AS AT
GROUP BY FIPS

示例输出:

00001   {"EnvConcEstimate":{"Benzene":10,"Lead":125},"NeuroNonCancer_HQ":{"Lead":125}}
20000   {"Cum_AirToxicCancer":{"None":275},"Cum_AirToxicNonCancerNeuro":{"None":215},"Cum_AirToxicNonCancerRespir":{"None":250},"EnvConcEstimate":{"Benzene":210,"Lead":2125},"NeuroNonCancer_HQ":{"Lead":2125}}

Fiddle: http://sqlfiddle.com/#!6/c73e4/13