我正在尝试调整路线管理。
我们有与邮政编码范围相关的路线代码。它们用于在交付订单时选择正确的运输路线。
一条路线将具有其活动的邮政编码范围,并且可能有一个客户端——如果该路线仅针对该客户端。
因此,路由表如下所示:
route_no | zipfrom | zipto | client
-----------------------+---------+-------+----------
ROUTE-CLIENTA-SPECIAL | 12330 | 12350 | CLIENT-A
ROUTE-CLB1 | 33331 | 44445 | CLIENT-B
ROUTE-SCENIC | 11111 | 99999 |
(3 rows)
所以,根据这张表:
- 每个订单都必须经过 ROUTE-SCENIC,包括客户 CLIENT-A 和 CLIENT-B。
- 除非订单是针对 CLIENT-A 的并且交付是针对邮政编码在 12330-12350 之间的地址——这些通过 ROUTE-CLIENTA-SPECIAL 进行。
- 或者它是 CLIENT-B 的订单,并且订单的邮政编码在 33331 和 44445 之间——然后它转到路由 ROUTE-CLB1
所以,对于今天的订单:
order_id | client | route_no | zip
----------+----------+----------+-------
123 | CLIENT-A | | 12345
124 | CLIENT-A | | 33333
125 | CLIENT-A | |
N988 | CLIENT-B | | 77777
N987 | CLIENT-B | | 33335
N0981 | CLIENT-B | | 44444
N0983 | CLIENT-B | | 12345
要获得 CLIENT-B 订单 N987 的可能路线(邮政编码 33333),我可以这样做:
SELECT client,route_no FROM routes
WHERE (client='CLIENT-B' OR client IS NULL )
AND '33333' BETWEEN zipfrom AND zipto ORDER BY client;
client | route_no
----------+--------------
CLIENT-B | ROUTE-CLB1
| ROUTE-SCENIC
(2 rows)
在这个 ROUTE-CLB1 之外是正确的路由(它比默认路由更具体到客户端)。
我可以通过 ORDER BY 和 LIMIT 1 始终选择正确的路线。
但我需要用正确的路线更新订单表。我可以用子查询来做到这一点:
UPDATE orders AS O
SET route_no=(SELECT R.route_no FROM routes R
WHERE (O.client=R.client OR R.client IS NULL )
AND O.zip BETWEEN R.zipfrom AND R.zipto
ORDER BY R.client LIMIT 1);
这给出了正确的答案:
id | client | route_no | zip
-------+----------+-----------------------+-------
123 | CLIENT-A | ROUTE-CLIENTA-SPECIAL | 12345
124 | CLIENT-A | ROUTE-SCENIC | 33333
125 | CLIENT-A | |
N988 | CLIENT-B | ROUTE-SCENIC | 77777
N987 | CLIENT-B | ROUTE-CLB1 | 33335
N0981 | CLIENT-B | ROUTE-CLB1 | 44444
N0983 | CLIENT-B | ROUTE-SCENIC | 12345
(7 rows)
但这在较大的订单列表上往往非常慢,因为子查询针对每一行运行。
我该如何改进它?我尝试按照在每个 GROUP BY 组中选择第一行中的描述使用 DISTINCT ON ?但这似乎不起作用。