2017-06-29 16 views
1

私は天秤とカレンダーという2つのテーブルを持っています。SQLでの結合中に行の上限を制限する方法はありますか?

バランス:

  • 私は最大値まですべてのアカウントのために不足している日を記入する必要があります:私は、次の操作を行う必要があり

     
    Account Date  Balance 
    1111 01/01/2014 100 
    1111 02/01/2014 156 
    1111 03/01/2014 300 
    1111 04/01/2014 300 
    1111 07/01/2014 468 
    
    1112 02/01/2014 300 
    1112 03/01/2014 300 
    1112 06/01/2014 300 
    1112 07/01/2014 350 
    1112 08/01/2014 400 
    1112 09/01/2014 450 
    
    1113 01/01/2014 30 
    1113 02/01/2014 40 
    1113 03/01/2014 45 
    1113 06/01/2014 45 
    1113 07/01/2014 60 
    1113 08/01/2014 50 
    1113 09/01/2014 20 
    1113 10/01/2014 10 
    

    カレンダー

     
    date  business_day_ind 
    01/01/2014 N 
    02/01/2014 Y 
    03/01/2014 Y 
    04/01/2014 N 
    05/01/2014 N 
    06/01/2014 Y 
    07/01/2014 Y 
    08/01/2014 Y 
    09/01/2014 Y 
    10/01/2014 Y 
    

    それが価値を持つ日。アカウント1111と言えば、2014年7月1日までの値しかないため、日付はその日付までに入力する必要があります。しかし、私がカレンダーテーブル(普通の左結合)に参加するとき、私は最大日をアカウントで利用可能な日に制限できません。私は1111,09/01/2014の場合、2014年7月1日(アカウントの最大残高利用可能日までの日数を制限するための効率的な方法(好ましくは複数のステップを含まない)を必要とする

 
1111 01/01/2014 100 N 
1111 02/01/2014 156 Y 
1111 03/01/2014 300 Y 
1111 04/01/2014 300 Y 
1111 05/01/2014  N 
1111 06/01/2014  N 
1111 07/01/2014 468 Y 
1111 08/01/2014  Y 
1111 09/01/2014  Y 
1111 10/01/2014  Y 

1112 01/01/2014  N 
1112 02/01/2014 300 Y 
1112 03/01/2014 300 Y 
1112 04/01/2014  N 
1112 05/01/2014  N 
1112 06/01/2014 300 Y 
1112 07/01/2014 350 Y 
1112 08/01/2014 400 Y 
1112 09/01/2014 450 Y 
1112 10/01/2014  Y 

ケース1112)

所望の出力に:行方不明の日を充填した後

 
1111 01/01/2014 100 N 
1111 02/01/2014 156 Y 
1111 03/01/2014 300 Y 
1111 04/01/2014 300 Y 
1111 05/01/2014  N 
1111 06/01/2014  N 
1111 07/01/2014 468 Y 

1112 01/01/2014  N 
1112 02/01/2014 300 Y 
1112 03/01/2014 300 Y 
1112 04/01/2014  N 
1112 05/01/2014  N 
1112 06/01/2014 300 Y 
1112 07/01/2014 350 Y 
1112 08/01/2014 400 Y 
1112 09/01/2014 450 Y 

、私は行方不明の日、前営業日のバランスを転嫁する予定です。私はすべての日付の前営業日を取得し、元の残高テーブルにacctおよび前営業日をキーとして参加させることで、不足行を更新する予定です。

ありがとうございました。

私はGreenplumデータベースです。

+1

希望の出力を追加できますか?それはちょっと混乱しています! –

+0

私はそれを追加しました。 – CuriP

答えて

0

可能な方法は、サブクエリに2番目の選択を入れることです。例えば:

select ... from calendar a left outer join balance b on a.date = b.date 
where a.date <= (select max(date) from balance c where b.Account = c.Account)  
0

私は、あなたが第三のテーブルがあるとしaccounts:楽しい課題でした

select 
    accounts.account, 
    calendar.date, 
    balance.balance, 
    calendar.business_day_ind 
from 
    accounts cross join lateral (
    select * 
    from calendar 
    where calendar.date <= (
     select max(date) 
     from balance 
     where balance.account = accounts.account)) as calendar left join 
    balance on (balance.account = accounts.account and balance.date = calendar.date) 
order by 
    accounts.account, calendar.date; 

About lateral joins

0

CREATE TABLE balance 
(account int, balance_date timestamp, balance int) 
DISTRIBUTED BY (account, balance_date); 

INSERT INTO balance 
values (1111,'01/01/2014', 100), 
(1111, '02/01/2014', 156), 
(1111, '03/01/2014', 300), 
(1111, '04/01/2014', 300), 
(1111, '07/01/2014', 468), 
(1112, '02/01/2014', 300), 
(1112, '03/01/2014', 300), 
(1112, '06/01/2014', 300), 
(1112, '07/01/2014', 350), 
(1112, '08/01/2014', 400), 
(1112, '09/01/2014', 450), 
(1113, '01/01/2014', 30), 
(1113, '02/01/2014', 40), 
(1113, '03/01/2014', 45), 
(1113, '06/01/2014', 45), 
(1113, '07/01/2014', 60), 
(1113, '08/01/2014', 50), 
(1113, '09/01/2014', 20), 
(1113, '10/01/2014', 10); 

CREATE TABLE calendar 
(calendar_date timestamp, business_day_ind boolean) 
DISTRIBUTED BY (calendar_date); 

INSERT INTO calendar 
values ('01/01/2014', false), 
('02/01/2014', true), 
('03/01/2014', true), 
('04/01/2014', false), 
('05/01/2014', false), 
('06/01/2014', true), 
('07/01/2014', true), 
('08/01/2014', true), 
('09/01/2014', true), 
('10/01/2014', true); 

analyze balance; 
analyze calendar; 

これでクエリになりました。

select d.account, d.my_date, b.balance, c.business_day_ind 
from (
    select account, start_date + interval '1 month' * (generate_series(0, duration)) AS my_date 
    from (
     select account, start_date, (date_part('year', duration) * 12 + date_part('month', duration))::int as duration 
     from (
      select start_date, age(end_date, start_date) as duration, account 
      from (
       select account, min(balance_date) as start_date, max(balance_date) as end_date 
       from balance 
       group by account 
       ) as sub1 
      ) as sub2 
     ) sub3 
    ) as d 
left outer join balance b on d.account = b.account and d.my_date = b.balance_date 
join calendar c on c.calendar_date = d.my_date 
order by d.account, d.my_date; 

結果:

account |  my_date  | balance | business_day_ind 
---------+---------------------+---------+------------------ 
    1111 | 2014-01-01 00:00:00 |  100 | f 
    1111 | 2014-02-01 00:00:00 |  156 | t 
    1111 | 2014-03-01 00:00:00 |  300 | t 
    1111 | 2014-04-01 00:00:00 |  300 | f 
    1111 | 2014-05-01 00:00:00 |   | f 
    1111 | 2014-06-01 00:00:00 |   | t 
    1111 | 2014-07-01 00:00:00 |  468 | t 
    1112 | 2014-02-01 00:00:00 |  300 | t 
    1112 | 2014-03-01 00:00:00 |  300 | t 
    1112 | 2014-04-01 00:00:00 |   | f 
    1112 | 2014-05-01 00:00:00 |   | f 
    1112 | 2014-06-01 00:00:00 |  300 | t 
    1112 | 2014-07-01 00:00:00 |  350 | t 
    1112 | 2014-08-01 00:00:00 |  400 | t 
    1112 | 2014-09-01 00:00:00 |  450 | t 
    1113 | 2014-01-01 00:00:00 |  30 | f 
    1113 | 2014-02-01 00:00:00 |  40 | t 
    1113 | 2014-03-01 00:00:00 |  45 | t 
    1113 | 2014-04-01 00:00:00 |   | f 
    1113 | 2014-05-01 00:00:00 |   | f 
    1113 | 2014-06-01 00:00:00 |  45 | t 
    1113 | 2014-07-01 00:00:00 |  60 | t 
    1113 | 2014-08-01 00:00:00 |  50 | t 
    1113 | 2014-09-01 00:00:00 |  20 | t 
    1113 | 2014-10-01 00:00:00 |  10 | t 
(25 rows) 

私はアカウントごとに最小と最大の日付を取得し、2つの日付の間の数ヶ月を生成するgenerate_seriesを使用する必要がありました。あなたは毎日レコードを必要とする場合は、少しきれいなクエリでしたが、毎月のレベルで結果を得るために別のサブクエリを使用しなければなりませんでした。

関連する問題