我的 PostgreSQL 数据库中有以下表格:
id | name | abbreviation
----+--------------------------+--------------
31 | 4705 Fifth Avenue - Dept | 4705FIFTH-D
28 | 4705 Fifth Avenue | 4705FIFTH
...
id | buildings_id | networks_id
-----+--------------+-------------
143 | 31 | 159
144 | 31 | 160
147 | 28 | 153
148 | 28 | 154
149 | 28 | 155
159 | 31 | 179
...
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';
我做错了什么?
试试这个,想法是只有正确的 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