使用子查询和联接更新 PostgreSQL

问题描述 投票:0回答:1

我的 PostgreSQL 数据库中有以下表格:

  1. 建筑物
 id |           name           | abbreviation 
----+--------------------------+--------------
 31 | 4705 Fifth Avenue - Dept | 4705FIFTH-D
 28 | 4705 Fifth Avenue        | 4705FIFTH
...
  1. 建筑物_网络
 id  | buildings_id | networks_id 
-----+--------------+-------------
 143 |           31 |         159
 144 |           31 |         160
 147 |           28 |         153
 148 |           28 |         154
 149 |           28 |         155
 159 |           31 |         179
...
  1. 网络
 id  |          name          | display_name 
-----+------------------------+--------------------
 179 | 4705FIFTH-D -- fmcs    | fmcs (staff)
 153 | 4705FIFTH -- onboard   | onboard (residents)
 154 | 4705FIFTH -- private   | private (residents)
 155 | 4705FIFTH -- public    | public (residents)
 159 | 4705FIFTH-D -- onboard | onboard (staff)
 160 | 4705FIFTH-D -- private | private (staff
...

我正在尝试更新

buildings_networks
表,以便所有网络(包括名称中带有
-D
的网络)都与名称中不含
- Dept
的类似建筑物相关联。

使用上面的示例,

buildings_networks
表理想情况下应如下所示:

 id  | buildings_id | networks_id 
-----+--------------+-------------
 143 |           28 |         159
 144 |           28 |         160
 147 |           28 |         153
 148 |           28 |         154
 149 |           28 |         155
 159 |           28 |         179
...

我意识到这可以在示例中逐行完成,但是除了我在本示例中提供的建筑物和网络之外,还有许多其他建筑物和网络。因此,单个查询将节省大量时间。

其他建筑物多种多样,但每栋建筑物总有两座。第一个子集的名称末尾带有

- Dept
,例如
4705 Fifth Avenue - Dept
-Dept
建筑物始终有一个以
-D
结尾的缩写,例如
4705FIFTH-D
。建筑物的第二个子集的名称和缩写分别没有
- Dept
-D
4705 Fifth Avenue
4705FIFTH

此外,网络名称总是有两种。其中一个子集是名称第一部分末尾带有

-D
的子集,例如
4705FIFTH-D -- onboard
。另一个子集没有
-D
,如
4705FIFTH -- onboard

我试过这个:

UPDATE buildings_networks bn
SET buildings_id = subquery2.building_id
FROM (
  SELECT b2.id AS building_id, b2.name, b2.abbreviation, bn2.networks_id
  FROM buildings b2
  INNER JOIN buildings_networks bn2
  ON bn2.buildings_id = b2.id
  WHERE b2.abbreviation NOT LIKE '%-D'
) AS subquery2
INNER JOIN buildings b
ON b.id = subquery2.building_id
WHERE replace(b.abbreviation, '-D', '') LIKE subquery2.abbreviation
OR b.abbreviation LIKE subquery2.abbreviation;

这看起来很接近,但它将所有

buildings_id
值设置为单个值(例如,除了本示例中显示的记录之外,还有 400 多条记录)而不是每个建筑物。

此查询产生相同的(不需要的)结果:

UPDATE buildings_networks
SET buildings_id = (
  SELECT b2.id 
  FROM buildings b2 
  WHERE b2.abbreviation = REPLACE(b.abbreviation, '-D', '')
)
FROM buildings_networks bn
INNER JOIN buildings b 
ON b.id = bn.buildings_id
WHERE b.abbreviation LIKE '%-D';

我做错了什么?

sql postgresql
1个回答
0
投票

试试这个,想法是只有正确的 ID,然后加入正确的缩写

update buildings_networks  
set buildings_id = right_ids.id
from buildings 
join (
    select id, abbreviation 
      from buildings
     where abbreviation not like '%-D'
) right_ids on buildings.abbreviation like concat(right_ids.abbreviation, '%')
where buildings.id = buildings_networks.buildings_id
© www.soinside.com 2019 - 2024. All rights reserved.