我有一个表,其中包含一个项目的JSON字符串(键值对)列,我只想返回最大值的键值对
我可以这样进行:首先UNNEST
设置JSON对象,然后通过ORDER BY item, value (DESC)
取最大值,然后使用array_agg
获得最大的值。问题在于这意味着创建多个表并且速度很慢。我希望可以通过一次操作提取最大的键值对。
此:
| id | items |
| -- | ---------------------------------- |
| 1 | {Item1=7.3, Item2=1.3, Item3=9.8} |
| 2 | {Item2=4.4, Item3=5.2, Item1=0.1} |
| 3 | {Item5=6.6, Item2=1.4, Item4=1.5} |
| 4 | {Item6=0.9, Item7=11.2, Item4=8.1} |
应成为:
| id | item | value |
| -- | ----- | ----- |
| 1 | Item3 | 9.8 |
| 2 | Item3 | 5.2 |
| 3 | Item5 | 6.6 |
| 4 | Item7 | 11.2 |
我实际上不需要该值,只要该项目是JSON对象中的最大对象,那么以下内容也可以:
| id | item |
| -- | ----- |
| 1 | Item3 |
| 2 | Item3 |
| 3 | Item5 |
| 4 | Item7 |
答案 0 :(得分:4)
Presto's UNNEST
performance got improved在Presto 316中。但是,在这种情况下,您不需要UNNEST
。
您可以
map_entries
将您的JSON转换为键/值对的Arary reduce
数组以选择最高值的键
row
元素,因此使用positional access to row
elements with subscript operator,(available since Presto 314)非常方便使用类似查询
SELECT
id,
reduce(
-- conver JSON to array of key/value pairs
map_entries(CAST(data AS map(varchar, double))),
-- initial state for reduce (must be same type as key/value pairs)
(CAST(NULL AS varchar), -1e0), -- assuming your values cannot be negative
-- reduction function
(state, element) -> if(state[2] > element[2], state, element),
-- reduce output function
state -> state[1]
) AS top
FROM (VALUES
(1, JSON '{"Item1":7.3, "Item2":1.3, "Item3":9.8}'),
(4, JSON '{"Item6":0.9, "Item7":11.2, "Item4":8.1}'),
(5, JSON '{}'),
(6, NULL)
) t(id, data);
输出
id | top
----+-------
1 | Item3
4 | Item7
5 | NULL
6 | NULL
(4 rows)
答案 1 :(得分:2)
在子表中每行存储一个值。
CREATE TABLE child (
id INT NOT NULL,
item VARCHAR(6) NOT NULL,
value DECIMAL(9,1),
PRIMARY KEY (id, item)
);
您不必进行联接即可找到每个组中最大的联接,只需使用窗口功能即可:
WITH cte AS (
SELECT id, item, ROW_NUMBER() OVER (PARTITION BY id ORDER BY value DESC) AS rownum
FROM mytable
)
SELECT * FROM cte WHERE rownum = 1;
用JSON解决这个问题不是一个好主意。它会使您的表非规范化,使查询更难以设计,并且我预计它将使查询性能变差。