上下文
我正在为网站运行车辆路径问题的变体。布局就是这样。你有接送点,卡车和被拾取的物品。真正的诀窍是客户在一天内不会运行相同数量的班次,因此可以自定义。所以我会在运行时但不提前知道这一点。我正在尝试创建一个返回结果的查询,每个公交站点的行,每个班次的列和每个项目的ID的json数组,如下所示:
id | address | city | postalcode | shift1 | shift2 | shift3
-----+------------------+-----------+------------+----------+--------+--------
220 | 1471 N Lymestone | Anytown | 12345 | [14, 16] | [12] | [14]
221 | 108 D Ave | Anytown | 12345 | [15, 17] | | [15,16]
222 | 1434 Bryan Ave | Anytown | 12345 | [16] | [1,19] |
表格结构
我这里有三张相关的表格;只有停靠点地理位置的stops
表,包含拾取项ID的items
表,包含班次的shifts
表和itemstopassignemnt
表(请原谅命名,我继承了它,它有一个stop_id
shift_id
和item_id
分配一个项目,在该站点为该班次选择。
查询
所以在SO上钓鱼之后,我提出了以下问题:
SELECT * FROM crosstab(
$$SELECT stop_id,
'shift' || shift_id,
json_agg(item_id)
FROM itemstopassignemnt
GROUP BY stop_id, shift_id
ORDER BY 1,2$$
) AS (stop_id INTEGER, shift1 JSON, shift2 JSON, shift3 JSON);
这适用于三班制案例。我可以把它放在函数中以编程方式生成sql所以它动态地构造它,无论用户添加了多少班次。然后,我认为该函数必须返回setof record
或table()
。以下是我的问题:
答案 0 :(得分:1)
select
stop_id,
jsonb_object_agg('shift' || shift_id, items) as shift_items
from (
select
stop_id,
shift_id,
coalesce (
array_agg (item_id) filter (where item_id is not null),
array[]::int[]
) as items
from
itemstopassignemnt
right join
(
select shift_id, stop_id
from
(select distinct shift_id from itemStopAssignemnt) a
cross join
(select distinct stop_id from itemStopAssignemnt) b
) r using (stop_id, shift_id)
group by 1,2
) s
group by 1
;
stop_id | shift_items
---------+--------------------------------------------------------
220 | {"shift1": [14, 16], "shift2": [12], "shift3": [14]}
221 | {"shift1": [15, 17], "shift2": [], "shift3": [15, 16]}
222 | {"shift1": [16], "shift2": [1, 9], "shift3": []}
我没有加入stops
来缩短它,但应该是微不足道的。