CockroachDB中JSONB数组字段的差异总和

时间:2019-03-07 15:43:19

标签: json cockroachdb

我有一堆名为 text 的jsonb对象,它们均遵循名为 texts 的表中的相同结构,当通过以下查询选择时,其外观如下:

  

从文本限制1中选择jsonb_pretty(text);

[                                                                                                                                                                                                                                                                                                                                                                   
        [                                                                                                                                                                                                                                                                                                                                                               
            {                                                                                                                                                                                                                                                                                                                                                           
                "speaker": null,                                                                                                                                                                                                                                                                                                                                        
                "start": 0.02,                                                                                                                                                                                                                                                                                                                                      
                "stop": 2.25,                                                                                                                                                                                                                                                                                                                                       
                "text": "random text 123"                                                                                                                                                                                                                                                                                                     
            },                

            {                                                                                                                                                                                                                                                                                                                                                           
                "speaker": null,                                                                                                                                                                                                                                                                                                                                        
                "start": 291.45,                                                                                                                                                                                                                                                                                                                                    
                "stop": 291.88,                                                                                                                                                                                                                                                                                                                                     
                "text": "random text 123"                                                                                                                                                                                                                                                                                                                      
            },                                                                                                                                                                                                                                                                                                                                                          
            {                                                                                                                                                                                                                                                                                                                                                           
                "speaker": null,                                                                                                                                                                                                                                                                                                                                        
                "start": 292.07,                                                                                                                                                                                                                                                                                                                                    
                "stop": 293.63,                                                                                                                                                                                                                                                                                                                                     
                "text": "random text 123"                                                                                                                                                                                                                                                                                           
            }                                                                                                                                                                                                                                                                                                                                                           
       ],                                                                                                                                                                                                                                                                                                                                                              
  []                                                                                                                                                                                                                                                                                                                                                              
]  

我想总结一下表的jsonb对象中的所有差异(停止-开始)。

使得第一个对象的结果为:(2.25-0.02)+(291.88-291.45)+(293.63-292.07)= 4.22然后需要与表中的其余条目求和。

我尝试了多种查询对象的方法,但找不到任何有效的方法,将不胜感激任何帮助或指向正确方向的指针。

1 个答案:

答案 0 :(得分:1)

与CockroachDB一起使用的版本(已通过v2.1.5测试):

CREATE TABLE test_data (
    id serial primary key,
    data jsonb not null
);

INSERT INTO test_data (data) VALUES
    ('[[{"speaker":null,"start":0.02,"stop":2.25,"text":"random text 123"},{"speaker":null,"start":291.45,"stop":291.88,"text":"random text 123"},{"speaker":null,"start":292.07,"stop":293.63,"text":"random text 123"}],[]]'::jsonb),
    ('[[{"speaker":null,"start":0.05,"stop":1.97,"text":"random text 123"},{"speaker":null,"start":260.78,"stop":261.23,"text":"random text 123"},{"speaker":null,"start":272.07,"stop":273.73,"text":"random text 123"}],[]]'::jsonb)
;

SELECT test_data.id,
    sum((items.item->>'stop')::numeric - (items.item->>'start')::numeric)
FROM test_data
INNER JOIN (SELECT id, jsonb_array_elements(data#>'{0}'::string[]) AS item FROM test_data) AS items ON (items.id = test_data.id)
GROUP BY 1
ORDER BY 1;

...导致:

          id         | sum   
+--------------------+------+
  432708358512836609 | 4.22  
  432708358512869377 | 4.03  
(2 rows)

解释:

               tree               |    field    |    description     
+---------------------------------+-------------+-------------------+
  sort                            |             |                    
   │                              | order       | +id                
   └── group                      |             |                    
        │                         | aggregate 0 | id                 
        │                         | aggregate 1 | sum(column6)       
        │                         | group by    | @2                 
        └── render                |             |                    
             └── join             |             |                    
                  │               | type        | inner              
                  │               | equality    | (id) = (id)        
                  ├── project set |             |                    
                  │    └── scan   |             |                    
                  │               | table       | test_data@primary  
                  │               | spans       | ALL                
                  └── scan        |             |                    
                                  | table       | test_data@primary  
                                  | spans       | ALL                
(17 rows)

在PostgreSQL的全面支持下,您可以使用LATERAL联接和GROUP BY ROLLUP来获得总数:

SELECT id, sum((items->'stop')::numeric - (items->'start')::numeric)
FROM test_data, LATERAL jsonb_array_elements(data#>'{0}') AS items
GROUP BY rollup(1)
ORDER BY 1 NULLS LAST;

...结果:

 id | sum  
----+------
  1 | 4.22
  2 | 4.03
    | 8.25
(3 rows)

说明(由于没有联接和按索引排序,因此实际上比CockroachDB更简单)

                                           QUERY PLAN                                            
-------------------------------------------------------------------------------------------------
 GroupAggregate  (cost=0.16..4815.59 rows=1271 width=36)
   Group Key: test_data.id
   Group Key: ()
   ->  Nested Loop  (cost=0.16..2577.21 rows=127000 width=36)
         ->  Index Scan using test_data_pkey on test_data  (cost=0.15..37.20 rows=1270 width=36)
         ->  Function Scan on jsonb_array_elements items  (cost=0.01..1.00 rows=100 width=32)
(6 rows)