次の表があります。
NAME
Alex
Bob
Bob
Tim
Alex
Roger
以下を作成する必要があります。
Name Count Percentage
Alex 2 33%
Bob 2 33%
Roger 1 16.6%
Tim 1 16.6%
どこから始めればいいのかわかりません。カウントの最初のクエリは簡単です。
単一のSELECT
で可能:
_SELECT name, count(*), to_char((count(*) * 100.0
/ sum(count(*)) OVER ()), 'FM990.00" %"') AS percent
FROM t
GROUP BY 1
ORDER BY 1;
_
count(*)
関数の別の形式です で、count(<expression>)
よりも少し高速です。すべての列が_NOT NULL
_であると仮定すると、それ以外の場合は後者を使用する必要があります。
ウィンドウ集計関数sum(count(*)) OVER ()
を実行して、同じSELECT
の合計を取得できます。 SELECT
のイベントのシーケンスを考えてみましょう:
これは、2つではなくone順次スキャンを使用し、通常、合計数のサブクエリを使用する場合より2倍高速です。
to_char()
は出力をプレティッシュします。
_name count percent
-----------------------
Alex 2 33.33 %
Bob 2 33.33 %
Roger 1 16.67 %
Tim 1 16.67 %
_
これは Window Functions を使用する良い機会です:
create table names
(
id serial,
name text
);
insert into names (name)
values ('Alex'), ('Bob'), ('Bob'), ('Tim'), ('Alex'), ('Roger');
select distinct name, count(name) over (partition by name) as num,
round( (count(name) over (partition by name)::numeric /
count(name) over() ) * 100, 1) as pct
from names
order by num desc, name;
これにより、次のような出力が得られます。
NAME NUM PCT
Alex 2 33.3
Bob 2 33.3
Roger 1 16.7
Tim 1 16.7
少し異なるフォーマットが必要な場合は、丸めコードを微調整できます。 %
をpct
列の値に連結することもできますが、最初にtext
にキャストする必要があり、結果の列はtext
になりますnumeric
に(これはあなたの場合には問題ないかもしれません)。
このクエリスタイルの大きな利点の1つは、テーブルがより複雑になり、列が増える場合でも、そのデータを処理し、クエリで返すことができ、さらに、次の理由により、カウントおよびパーセンテージデータにアクセスできることです。ウィンドウ関数スコープの仕組み。個別を削除すると、同じ名前でも行ごとに取得できます。
SELECT name,COUNT(*), ROUND(100.0*COUNT(name)/(SELECT 100.0* count(name) FROM t),3) as percentage
FROM t GROUP BY name
私は少し浮気しているようですが、これはあなたの結果を得るはずです:
with c as(
select count(*) from "the_table"
), p as(
select name,count(*) from "the_table" group by name
)
select
p.name,
p.count,
((p.count * 100) / c.count) percentage
from p,c
order by name
1つの方法は、サブクエリを使用することです。
select
name,
count(*) as Count,
to_char(
count(*)/(select cast(count(*) as decimal) from Table1)*100,'99.99'
) ||'%' as Percentage
from Table1
group by name
SELECT name, COUNT(name) as Count, (COUNT(name) / (SELECT COUNT(name) FROM table_name)) AS Percentage
FROM table_name GROUP BY name;