PostgreSQL 连接两个值
PostgreSQL Joining Between Two Values
我有以下 table 并且正在尝试查找县代码以获得数十万个城市的列表。
create table counties (
zip_code_from char(5) not null,
zip_code_thru char(5) not null,
county_code char(3) not null
);
create table cities (
city text not null,
zip_code char(5) not null
);
我的第一种方法是在连接中使用 "between":
select
ci.city, ci.zip_code, co.county_code
from
cities ci
join counties co on
co.zip_code between ci.zip_code_from and ci.zip_code_thru
我知道在 Oracle 的世界里,这是不受欢迎的,而且确实表现得很糟糕。处理大约 16,000 个城市需要 8 多分钟。邮政编码 table 有大约 80,000 条记录。我猜这个语法是美化的交叉连接?
来自和通过代码都已编入索引,我可以控制结构,因此如果有帮助,我可以更改 table。
我唯一的其他想法是继续将 table 扩展到所有可能的值——类似于此:
select
generate_series (
cast (zip_code_from as int),
cast (zip_code_thru as int)
) as zip_code,
*
from counties
这会将数据扩展到超过 200,000 条记录,这不是什么大问题,但我不确定这是否是我获得不可怕查询的唯一途径。
我猜即使是在运行中执行此操作并且没有索引也比我的连接中的 between
更可取,但我希望有一个替代方案,无论是就我的 SQL and/or 我可以用 table 本身的结构做一些事情。
我已经看到针对其他 DBMS 平台发布的这个问题,但我已经能够使用 PostgreSQL 实现在其他数据库中不可能(或不实用)的迷你奇迹,所以我希望我错过了什么。
几个月后,它又出现了,我决定检验我的一些理论。
原查询:
select
ci.city, ci.zip_code, co.fips_code
from
cities ci
join counties co on
ci.zip_code between co.from_zip_code and co.thru_zip_code
确实实现了笛卡尔。查询 returns 34,000 行,耗时 597 秒。
如果我 "pre-explode" 将邮政编码范围分成离散记录:
with exploded_zip as (
select
generate_series (
cast (from_zip_code as int),
cast (thru_zip_code as int)
)::text as zip_code,
*
from counties
)
select
ci.city, ci.zip_code, co.fips_code
from
cities ci
join exploded_zip co on
ci.zip_code = co.zip_code
查询 returns 完全相同的行,但在 2.8 秒内完成。
所以底线似乎是在连接(或任何不等式)中使用 between
是一个非常糟糕的主意。
我有以下 table 并且正在尝试查找县代码以获得数十万个城市的列表。
create table counties (
zip_code_from char(5) not null,
zip_code_thru char(5) not null,
county_code char(3) not null
);
create table cities (
city text not null,
zip_code char(5) not null
);
我的第一种方法是在连接中使用 "between":
select
ci.city, ci.zip_code, co.county_code
from
cities ci
join counties co on
co.zip_code between ci.zip_code_from and ci.zip_code_thru
我知道在 Oracle 的世界里,这是不受欢迎的,而且确实表现得很糟糕。处理大约 16,000 个城市需要 8 多分钟。邮政编码 table 有大约 80,000 条记录。我猜这个语法是美化的交叉连接?
来自和通过代码都已编入索引,我可以控制结构,因此如果有帮助,我可以更改 table。
我唯一的其他想法是继续将 table 扩展到所有可能的值——类似于此:
select
generate_series (
cast (zip_code_from as int),
cast (zip_code_thru as int)
) as zip_code,
*
from counties
这会将数据扩展到超过 200,000 条记录,这不是什么大问题,但我不确定这是否是我获得不可怕查询的唯一途径。
我猜即使是在运行中执行此操作并且没有索引也比我的连接中的 between
更可取,但我希望有一个替代方案,无论是就我的 SQL and/or 我可以用 table 本身的结构做一些事情。
我已经看到针对其他 DBMS 平台发布的这个问题,但我已经能够使用 PostgreSQL 实现在其他数据库中不可能(或不实用)的迷你奇迹,所以我希望我错过了什么。
几个月后,它又出现了,我决定检验我的一些理论。
原查询:
select
ci.city, ci.zip_code, co.fips_code
from
cities ci
join counties co on
ci.zip_code between co.from_zip_code and co.thru_zip_code
确实实现了笛卡尔。查询 returns 34,000 行,耗时 597 秒。
如果我 "pre-explode" 将邮政编码范围分成离散记录:
with exploded_zip as (
select
generate_series (
cast (from_zip_code as int),
cast (thru_zip_code as int)
)::text as zip_code,
*
from counties
)
select
ci.city, ci.zip_code, co.fips_code
from
cities ci
join exploded_zip co on
ci.zip_code = co.zip_code
查询 returns 完全相同的行,但在 2.8 秒内完成。
所以底线似乎是在连接(或任何不等式)中使用 between
是一个非常糟糕的主意。