【PostgreSQL】unionした時に型が異なるエラーが出たときの解決方法

PostgreSQL
この記事は約4分で読めます。

PostgreSQLでunionした時に以下のような型が異なるエラーが出た場合の解決方法を解説します。

「UNION types character varying and bigint cannot be matched」

サンプルのテーブル作成

解説するために、以下のテーブルとデータを用意しておきます。

table_apopulationの方はbiginttable_bpopulationの方はvarcharにしています。

-- table_a作成
create table table_a(id int, city varchar, population bigint); 

-- table_aにサンプルデータ挿入
insert 
into table_a(id, city, population) 
values 
(1, 'A市', 832),
(2, 'B市', 333),
(3, 'C市', 111); 

-- table_b作成
create table table_b(id int, city varchar, population varchar);

-- table_bにサンプルデータ挿入
insert 
into table_b(id, city, population) 
values 
(1, 'D市', '732'),
(2, 'E市', '133'),
(3, 'F市', '311'); 

原因

先ほど作成したtable_atable_bの取得結果をUNIONでまとめて取得してみます。

-- table_aとtable_bからcityとpopulationを選択して、結果を一つにまとめる
select
    city
    , population 
from
    table_a 
union 
select
    city
    , population
from
    table_b;

このsqlを実行すると型が異なる旨のこのようなエラーが表示されます。UNION types bigint and character varying cannot be matched

このエラーの原因はtable_atable_bpopulationの型カテゴリが異なることです。table_apopulationの型カテゴリは数値型ですが、table_bの型カテゴリは文字型です。型カテゴリとはデータ型より大きな区分です。例えばintegerbigintは両方とも数値型に分類されます。(詳細はこちら

もしtable_bの型がbigintなどであれば、table_atable_bの型カテゴリが両方とも数値型でUNIONはエラーになりません。

実際にtable_bpopulationカラムの型をbigintに変更して先ほどのUNIONを実行してみます。

-- table_bのpopulationカラムの型をbigintに変更
alter table table_b alter column population type bigint 
    using (population ::integer);
select
    city
    , population 
from
    table_a 
union 
select
    city
    , population 
from
    table_b; 

正常に実行され、以下の結果を取得することが出来ました。

解決方法

解決方法はUNIONする前のそれぞれの結果のカラムの型カテゴリを揃えることです。

先ほどtable_bpopulationカラムの型をbigintに変更した場合は元のvarcharに戻しておきます。

-- table_bのpopulationカラムの型varcharに戻す
alter table table_b alter column population type varchar 
    using (population ::varchar);

UNIONするときに型を揃えるために、キャストして型変換をします。

select
    city
    , population 
from
    table_a 
union 
select
    city
    , population::int -- integer型にキャスト
from
    table_b; 

まとめ

  • 型カテゴリを揃えるためにキャストを行う
  • UNIONするときはカラムの型カテゴリを揃える必要がある

おすすめ書籍

タイトルとURLをコピーしました