質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

7689閲覧

SQL 累積集計での日付の歯抜け対応

sysder

総合スコア25

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

1クリップ

投稿2018/08/01 14:12

以下のテーブル(tableA)があったときに、tableBのように日付がないところを埋めてさらに累積の値で埋めたいです。
tableA

dt購入金額累積購入金額地域
1/31010岩手
1/41020岩手
1/61030岩手

tableB

dt購入金額累積購入金額地域
1/100岩手
1/200岩手
1/31010岩手
1/41020岩手
1/5020岩手
1/61030岩手

以下のコードを書いたのですが、どういうわけか連続の日ではなくなってしまいます。
どうすればtableBを作れるのでしょうか。

lang

1with 2dt_table AS ( 3SELECT 4 ('2018-01-01'::date + (ROW_NUMBER() OVER()) - 1)::date AS dt 5FROM 6 table -- 適当なテーブルを指定 7limit 8 366 9) 10SELECT 11 d.dt, 12 COALESCE(t.購入金額, 0) AS 購入金額, 13 (CASE WHEN t.累積購入金額 IS NULL THEN COALESCE(MAX(t.累積購入金額) OVER(PARTITION BY t.地域 ORDER BY d.dt ROWS UNBOUNDED PRECEDING), 0) ELSE t.累積購入金額 END) AS 累積購入金額, 14 (CASE WHEN t.地域 IS NULL THEN COALESCE(MAX(t.地域) OVER(PARTITION BY t.地域 ORDER BY d.dt ROWS UNBOUNDED PRECEDING), 0) ELSE t.地域 END) AS 地域 15FROM 16 dt_table d 17 LEFT JOIN tableA t 18 ON d.dt = t.dt

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

genarate_seriseが使えます。
postgres版

SQL

1SELECT 2 d.dt::date 3 , COALESCE(t.購入金額, 0) AS 購入金額 4 , coalesce((select 累積購入金額 from tableA where dt<=d.dt order by dt desc limit 1), 0) as 累積購入金額 5 , '岩手' as 地域 6FROM 7 generate_series('2018/01/01'::date,'2018/12/31'::date, '1 days') as d(dt) 8 left JOIN tableA t ON d.dt=t.dt and t.地域='岩手' 9order by d.dt

データが無い日から開始する場合、累積は0とすれば取れますけど、地域は無理ですね。
何らかの基準が無いと。
redshift版(但し環境がなく未確認)

SQL

1with 2 dt_table AS ( 3 SELECT ('2018-01-01'::date + (ROW_NUMBER() OVER()) - 1)::date AS dt 4 FROM table -- 適当なテーブルを指定 5 limit 366 6) 7select 8 d.dt::date 9 , COALESCE(t.購入金額, 0) AS 購入金額 10 , coalesce((select 累積購入金額 from tableA where dt<=d.dt order by dt desc limit 1), 0) as 累積購入金額 11 , '岩手' as 地域 12FROM dt_table d LEFT JOIN tableA t ON d.dt=t.dt and t.地域='岩手'

投稿2018/08/01 14:48

編集2018/08/02 03:38
sazi

総合スコア25173

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sysder

2018/08/01 15:14

ご回答ありがとうございます。 redshiftなのでgenerate_seriesが使えないのです。 また日付を作るところまではできています。 その次のselectでcaseで累積を引っ張って来る所が上手くいってないようです。
sazi

2018/08/01 15:22

redshiftですか。後出ししないようにして下さい。 低速だと思いますが、累積部分は回答の内容でも大丈夫だと思います。
sazi

2018/08/01 15:28 編集

ん?結果は出ていて並びだけ正しくないってことですか? もしそうなら、order by 付けるだけでは?
sysder

2018/08/01 15:31

後出しすみませんでした。 with句の中のみを流すと日付が1日ごとに得られます。 with句のあとのleft joinで何故か日付が抜け落ちます。
sazi

2018/08/01 15:37

結合が上手くいってないんじゃないでしょうか。 castして型を合わせてみて下さい。
sysder

2018/08/01 15:42

型は一致してました。 selectのcase文の所を2つとも削除して流すと日付が連続してちゃんと出力されました。
sazi

2018/08/01 15:45

多分、max使ってるからです。 暗黙でgroup by されているんでしょう。
sysder

2018/08/01 15:50

なるほど。確かにそんな気がします。 LAGでやってみたら2日以上空きがあるとnullが返ってきて上手くいかなかったのですが、何か別のやり方はありませんか?
sazi

2018/08/01 16:10 編集

累計に関しては回答してますよ。 結局、無いものは作れないので、地域は難しいでしょうね。 起点としてのデータがあれば、再帰が使えればという所ですけど、使えないみたいですし。
sazi

2018/08/01 16:10

地域を限定すれば固定にできるので、結局累計だけで良いという事になります。
sysder

2018/08/01 16:17

1/1と1/2は諦めるとして、1/3以降を上手く集計する方法はないでしょうか。
sazi

2018/08/01 16:27

追記しました。地域は限定するしか思いつきません。
sazi

2018/08/01 16:30

地域のマスタがあれば、with部分で日付と地域を組み合わせた内容にすれば、良さそう。
sysder

2018/08/01 23:05 編集

ありがとうございます。 元データから地域マスタを作ってやってみます。 with句ではdtと地域のcross joinですか? またleft joinのところは以下ですか? dt_table d LEFT JOIN tableA t ON d.dt = t.dt AND d.地域 = t.地域
sazi

2018/08/02 00:00

ですね。で、利用はd.地域
sysder

2018/08/02 03:04

何度もすみません。 coalesceの中にselect文を書いたら相関サブクエリはダメですというエラーが出ました。カッコを忘れずに付けたのですが…
sazi

2018/08/02 03:31 編集

じゃあ、ネストしてみて下さい。こちらにはredshiftの環境は無いので。
sysder

2018/08/02 03:57

tableAの後にtをつけて、t.累積購入金額とやったら解決しました。謎です。 coalesce((select t.累積購入金額 from tableA t where...
sysder

2018/08/02 04:23

とりあえず午後もガチャガチャやってみます。 またありがとうございました。 また何かありましたらよろしくお願いします。
sysder

2018/08/02 14:33

お陰様でうまく集計できました。 大変助かりました。 ありがとうございました。
guest

0

WITH句のなかでdt_table を呼び出さないといけないかと思います。
PostgreSQLで試しましたが、1~10までカウントアップするのは以下のSQLで作成できます。

WITH RECURSIVE temp AS( SELECT 1 AS CNT --初期値 UNION ALL SELECT CNT + 1 FROM temp --増分 ) SELECT * FROM temp LIMIT 10

あとは、これを日付型に置き換えたら良いかと思います。

WITH RECURSIVE temp AS( SELECT TO_DATE('20180101', 'YYYYMMDD') AS CNT UNION ALL SELECT CNT + 1 FROM temp ) SELECT * FROM temp LIMIT 365

投稿2018/08/01 14:31

appdev

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sysder

2018/08/01 14:38

ご回答ありがとうございます。 最初のwith句はちゃんと日付が連続して出ていることを確認しています。
sysder

2018/08/01 14:38

ちなみにRedshiftを使ってます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問