在json数组列上加入Postgresql表

时间:2016-06-25 20:20:02

标签: sql json postgresql

我在postgresql中有两个表,其中包含json数组列tableA.BtableB.B。如何在这些json列上连接这些表? 即

select tableA.id, tablA.A, tableB.id,tableA.B, tableB.name
from tableA, tableB 
where tableA.B = tableB.B 

--tableA--
id | A     | B                 
1  | 36464 | ["874746", "474657"] 
2  | 36465 | ["874748"] 
3  | 36466 | ["874736", "474654"] 

--tableB--
id | name  | B                 
1  | john  | ["8740246", "2474657"] 
2  | mary  | ["874748","874736"] 
3  | clara | ["874736", "474654"] 

2 个答案:

答案 0 :(得分:3)

实际上,对于 Postgres 9.4 或更高版本中的数据类型 jsonb ,这将变为死简单。您的查询将起作用(丑陋的命名约定,输出中的代码和重复名称除外)。

CREATE TEMP TABLE table_a(a_id int, a int, b jsonb);
INSERT INTO table_a VALUES
  (1, 36464, '["874746", "474657"]')
, (2, 36465, '["874748"]')
, (3, 36466, '["874736", "474654"]');

CREATE TEMP TABLE table_b(b_id int, name text, b jsonb);
INSERT INTO table_b VALUES
  (1, 'john' , '["8740246", "2474657"]')
, (2, 'mary' , '["874748","874736"]')
, (3, 'clara', '["874736", "474654"]');

查询:

SELECT a_id, a, b.*
FROM   table_a a
JOIN   table_b b USING (b);  -- match on the whole jsonb column

您甚至要求表明您正在使用数据类型json,其中不存在相等运算符:

你刚才没有提到最重要的细节。

显而易见的解决方案是切换到jsonb

回答your comment

  

是否可以将b压缩为新行而不是数组?

LATERAL加入中使用jsonb_array_elements(jsonb) or jsonb_array_elements_text(jsonb)

SELECT a_id, a, b.b_id, b.name, b_array_element
FROM   table_a a
JOIN   table_b b USING (b)
     , jsonb_array_elements_text(b) b_array_element

这仅返回整个数组上匹配的行。关于LATERAL

如果您想匹配数组元素,请在加入之前取消您的数组。
整个设置似乎迫切需要normalization

答案 1 :(得分:0)

WITH tableA AS
  (SELECT 1 AS id,
          36464 AS A,
          '["874746", "474657"]'::jsonb AS B
   UNION SELECT 2 AS id,
                36465 AS A,
                '["874748"]'::jsonb AS B
   UNION SELECT 3 AS id,
                36466 AS A,
                '["874736", "474654"]'::jsonb AS B),
     tableB AS
  ( SELECT 1 AS id,
           'john' AS name,
           '["8740246", "2474657"]'::jsonb AS B
   UNION SELECT 2 AS id,
                'mary' AS name,
                '["874748", "874736"]'::jsonb AS B
   UNION SELECT 3 AS id,
                'clara' AS name,
                '["874736", "474654"]'::jsonb AS B)
SELECT *
FROM tableA
inner join tableB using(B);

给你

          b           | id |   a   | id | name  
----------------------+----+-------+----+-------
 ["874736", "474654"] |  3 | 36466 |  3 | clara

这不是你所期望的吗?