簡體   English   中英

postgresql jsonb 按內部屬性查詢

[英]postgresql jsonb query by inner property

我正在使用 postgresql 10.6。 我的表有一個 jsonb 列travel ,其中填充了以下示例數據。 下面是sqlfiddle;

http://sqlfiddle.com/#!17/e52ff/1

我的桌子:

id | travel                                                                                                                                                                                                   
-: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1 | {"name": "Lucy", "trips": [{"city": "Tokyo", "continent": "Asia"}, {"city": "Bangkok", "continent": "Asia"}, {"city": "Paris", "continent": "Europe"}, {"city": "London", "continent": "Europe"}]}       
 2 | {"name": "Tom", "trips": [{"city": "Tokyo", "continent": "Asia"}, {"city": "Kyoto", "continent": "Asia"}, {"city": "Frankfurt", "continent": "Europe"}, {"city": "London", "continent": "Europe"}]}      
 3 | {"name": "Lenny", "trips": [{"city": "Tokyo", "continent": "Asia"}, {"city": "Bangkok", "continent": "Asia"}, {"city": "New York", "continent": "America"}, {"city": "Seattle", "continent": "America"}]}

DDL 和插入代碼:

create table people (
    id serial primary key,
    travel jsonb
);

insert into people (travel) values (
'{
    "name": "Lucy",
    "trips": [
      {
        "continent": "Asia",
        "city": "Tokyo"
      },
      {
        "continent": "Asia",
        "city": "Bangkok"
      },
      {
        "continent": "Europe",
        "city": "Paris"
      },
      {
        "continent": "Europe",
        "city": "London"
      }
    ]
  }
'::jsonb);

insert into people (travel) values (
'{
    "name": "Tom",
    "trips": [
      {
        "continent": "Asia",
        "city": "Tokyo"
      },
      {
        "continent": "Asia",
        "city": "Kyoto"
      },
      {
        "continent": "Europe",
        "city": "Frankfurt"
      },
      {
        "continent": "Europe",
        "city": "London"
      }
    ]
  }
'::jsonb);

insert into people (travel) values (
'{
    "name": "Lenny",
    "trips": [
      {
        "continent": "Asia",
        "city": "Tokyo"
      },
      {
        "continent": "Asia",
        "city": "Bangkok"
      },
      {
        "continent": "America",
        "city": "New York"
      },
      {
        "continent": "America",
        "city": "Seattle"
      }
    ]
  }
'::jsonb);

如何查詢到亞洲大陸有“o”字母的城市的旅行?

感謝和問候

我認為您自己的答案很好。 數組選擇可以簡化一點,大陸過濾條件的重復有點難看——我大概會寫

SELECT *
FROM (
  SELECT
    travel -> 'name' as name,
    ARRAY(
      SELECT mytrips
      FROM jsonb_array_elements(travel -> 'trips') mytrips
      WHERE mytrips ->> 'continent' = 'Europe'
    ) as trips
  FROM
    people
  ) t
WHERE 
  trips <> '{}'

在線演示
另一方面,如果您在travel上有索引,則WHERE子句中的@>運算符可能會更快。

可能更簡單,但對於同一個人的多次旅行具有不同的語義,將是一種分組方法:

SELECT travel -> 'name' as name, jsonb_agg(trip) as trips
FROM people, jsonb_array_elements(travel -> 'trips') trip
WHERE trip ->> 'continent' = 'Europe'
GROUP BY name

在線演示

我不太清楚您期望的 output 是什么。 但是要在Asia找到帶有o的城市是這樣的:

演示:db<>小提琴

SELECT 
    * 
FROM 
    people,
    jsonb_array_elements(travel -> 'trips') elems
WHERE
    elems ->> 'city' LIKE '%o%'
    AND elems ->> 'continent' = 'Asia'
  1. 將數組元素分別展開為一行
  2. continentcity過濾

我可以通過以下查詢獲得我想要的結果。 但是,我不確定它是否在性能方面是最佳的。 有什么建議可以讓它表現得更好嗎?

SELECT
  travel -> 'name',   
   Array(      
      (SELECT elements.mytrips FROM
       (SELECT jsonb_array_elements(travel -> 'trips') as mytrips) as elements  
       WHERE elements.mytrips ->> 'continent' = 'Europe'
      )     
    )   
FROM 
  people
WHERE 
  travel -> 'trips' @> '[{"continent": "Europe"}]'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM