Select json 中使用 PostgreSQL 的特定条目

Select a specific entry in json with PostgreSQL

我有以下 JSON 存储在 PostgreSQL 数据库中名为 "Data" 的 jsonb 字段中:

{
    "CompetitionData" :
    {
        "StartDate" : "12.06.2018",
        "Name" : "TestCompetition",
        "Competitors" :
        [
            {
                "Id" : "100",
                "Name" : "John",
                "Age" : "24",
                "Score" : "98",
                "Shoes":
                {
                    "Brand" : "Nike"
                }
            },
            {
                "Id" : "200",
                "Name" : "Adam",
                "Age" : "32",
                "Score" : "78",
                "Shoes":
                {
                    "Brand" : "Adidas"
                }
            }
        ]
    }
}

我正在尝试在 Competitors 中获取特定条目,例如

SELECT * FROM Competitors WHERE Shoes = "Nike";

结果必须如下所示:

{
       "Id" : "100",
       "Name" : "John",
       "Age" : "24",
       "Score" : "98",
       "Shoes":
       {
           "Brand" : "Nike"
       }
}

我尝试了以下查询,但我保持 returning 所有竞争对手:

SELECT jsonb_array_elements(public."Competitions"."Data"->'CompetitionData'->'Competitors') as test
FROM public."Competitions" WHERE public."Competitions"."Data" @> '{"CompetitionData":{"Competitors":[{"Shoes":{"Brand":"Nike"}}]}}';

是否有可能 return 只是鞋子品牌 "Nike" 的竞争对手?

为什么要保存在jsonb中?只需将其规范化到数据库中即可:

CREATE TABLE competitor_shoe (
  name  text PRIMARY KEY,
  brand text NOT NULL
);

CREATE TABLE competitor (
  id    int  PRIMARY KEY,
  name  text NOT NULL,
  age   int  NOT NULL,
  score int  NOT NULL,
  shoe  text NOT NULL REFERENCES competitor_shoe(name)
);

CREATE TABLE competition (
  name       text PRIMARY KEY, 
  start_date date NOT NULL
);

CREATE TABLE competition_competitor (
  competition text REFERENCES competition,
  competitor  int  REFERENCES competitor,
  PRIMARY KEY (competition,competitor)
);


INSERT INTO competitor_shoe
VALUES ('shoes1', 'Nike'), 
  ('shoes2', 'Adidas');

INSERT INTO competitor 
VALUES (100,'John',24,98,'shoes1'),
  (200,'Adam',32,78,'shoes2');

INSERT INTO competition 
VALUES (
  'TestCompetition',
  '12.06.2018'
);

INSERT INTO competition_competitor
VALUES ('TestCompetition', 100), ('TestCompetition', 200);


-- query the data
SELECT * 
FROM   competitor c
JOIN   competitor_shoe cs
ON     c.shoe = cs.name
WHERE  brand = 'Nike';

-- query the data and return it as json object
SELECT to_jsonb(c) || jsonb_build_object('shoe', to_jsonb(cs)) as data
FROM   competitor c
JOIN   competitor_shoe cs
ON     c.shoe = cs.name
WHERE  brand = 'Nike';

在 from 子句中使用 jsonb_array_elements

SELECT j.* FROM
t cross join lateral 
  jsonb_array_elements(data->'CompetitionData'->'Competitors') as j(comp)
where j.comp->'Shoes'->>'Brand' = 'Nike'

Demo