2016-04-28 6 views
1

私は18歳から24歳までの店舗に来る顧客の数を1か所あたりで取得するためのクエリを実行できます。 私はこのようにそれをやっている:PostgreSQLのいくつかの日付範囲で発生数をカウントする方法

select year, month, shop_id, count(birthday) 
from customers 
where birthday 
BETWEEN '1992-01-01 00:00:00' AND '1998-01-01 00:00:00' 
group by year, month, shop_id; 

を今、私は同時にいくつかの範囲のために、このクエリを作る問題を抱えています。

私は現在、このデータベーススキーマがあります。

shop_id | birthday | year | month | 
--------+----------+------+-------- 
567 | 1998-10-10 | 2014 | 10 | 
567 | 1996-10-10 | 2014 | 10 | 
567 | 1985-10-10 | 2014 | 10 | 
234 | 1990-10-10 | 2014 | 10 | 
123 | 1970-01-10 | 2014 | 10 | 
123 | 1974-01-10 | 2014 | 11 | 

をそして、私はこのような何かを取得したいと思います:最初のクエリでは

shop_id | year | month | 18 < age < 25 | 26 < age < 35 
--------+------+-------+---------------+------------- 
567 | 2014 | 10 | 2    | 1 
234 | 2014 | 10 | 1    | 0 
123 | 2014 | 10 | 0    | 0 

を、それが1店が持っているケースを管理していませんいいえ顧客。存在しない場合は0を得る方法?

複数の日付範囲を同時に照会するにはどうすればよいですか?

+0

各年齢グループに1つずつ、選択リストに大文字/小文字の表記があります。例えば。 (今日の時点で – jarlh

+0

年齢? –

答えて

0

代わりのフィルタ、ユースケース文:

select year, month, shop_id, 
count(case when birthday between <range1> then 1 end) RANGE1, 
count(case when birthday between <range2> then 1 end) RANGE2, 
count(case when birthday between <range3> then 1 end) RANGE3 
from customers 
group by year, month, shop_id; 
+1

ありがとう!シンプルで効率的です。 – KillianKemps

0

「ゼロの行は、」GROUP BYクエリに共通する問題です。解決策は、FROMを完全なリストを持つテーブルにすることです。次にLEFT JOINを実行します。年と月でグループ分けしているので、年と月の完全なリストを作成する必要があります。あなたはgenerate_seriesであることを行うことができます。

SELECT t.t, s.id, COUNT(c.birthday) 
FROM shops s 
CROSS JOIN generate_series('2014-01-01 00:00:00', '2015-01-01 00:00:00', interval '1 month') t(t) 
LEFT OUTER JOIN customers c 
ON  c.shop_id = s.id 
AND  c.birthday 
     BETWEEN '1992-01-01 00:00:00' AND '1998-01-01 00:00:00' 
AND  c.year = EXTRACT(YEAR FROM t.t) 
AND  c.month = EXTRACT(MONTH FROM t.t) 
GROUP BY t.t, s.id 
ORDER BY s.id, t.t; 

あなたはMO2 @示唆、またはあなたが二回customersテーブルに参加することができるもの行うことができ、2つの日付範囲のカウントを取得するには:

SELECT t.t, s.id, COUNT(DISTINCT c1.id), COUNT(DISTINCT c2.id) 
FROM shops s 
CROSS JOIN generate_series('2014-01-01 00:00:00', '2015-01-01 00:00:00', interval '1 month') t(t) 
LEFT OUTER JOIN customers c1 
ON  c1.shop_id = s.id 
AND  c1.birthday 
     BETWEEN '1992-01-01 00:00:00' AND '1998-01-01 00:00:00' 
AND  c1.year = EXTRACT(YEAR FROM t.t) 
AND  c1.month = EXTRACT(MONTH FROM t.t) 
LEFT OUTER JOIN customers c2 
ON  c2.shop_id = s.id 
AND  c2.birthday 
     BETWEEN '1982-01-01 00:00:00' AND '1992-01-01 00:00:00' 
AND  c2.year = EXTRACT(YEAR FROM t.t) 
AND  c2.month = EXTRACT(MONTH FROM t.t) 
GROUP BY t.t, s.id 
ORDER BY s.id, t.t; 

注意であることどちらのクエリでも、yearmonthではなく、完全な日時を入力しているSELECTです。それは私が思うに柔軟性がありますが、必要ならば変更するのは簡単なはずです。

EDIT

は、私はあなたの yearmonthが誕生日に関連していないですが、何か他のものは、私が訪問日を推測実現しましたか?だから私は私のクエリを更新しました。一度に1ヶ月しかチェックしない場合は、 generate_seriesを削除し、年と月の整数を直接ジョイン条件に入れてください。

関連する問題