A B C
0 10062-35551-49007-45097 8/31/2014 0:00 233
1 10062-35551-49007-45097 10/31/2014 0:00 14
2 10062-35551-49007-45097 12/31/2014 0:00 22
BとCの日付範囲の間のすべての月が、次のようにその日付範囲で繰り返されるため、出力が必要です。
A B C
0 10062-35551-49007-45097 8/31/2014 0:00 233
1 10062-35551-49007-45097 9/30/2014 0:00 233
2 10062-35551-49007-45097 10/31/2014 0:00 14
3 10062-35551-49007-45097 11/30/2014 0:00 14
4 10062-35551-49007-45097 12/31/2014 0:00 22
この問題に対処する一般的な方法は、最初に、月末の日付のリストを保持する参照テーブルを作成することです。これは最初は少し余分な努力のように思えるかもしれませんが、これにはクエリの記述がはるかに簡単になるという利点があります(そして主にRDBMSに依存しません)。
テーブルを作成しall_dates
、2014年のすべての月末日を保存するとします。
create table all_dates (dt date not null primary key);
insert into all_dates values('2014-01-31');
insert into all_dates values('2014-02-28');
insert into all_dates values('2014-03-31');
insert into all_dates values('2014-04-30');
insert into all_dates values('2014-05-31');
insert into all_dates values('2014-06-30');
insert into all_dates values('2014-07-31');
insert into all_dates values('2014-08-31');
insert into all_dates values('2014-09-30');
insert into all_dates values('2014-10-31');
insert into all_dates values('2014-11-30');
insert into all_dates values('2014-12-31');
これで、次のようなクエリを記述できます。
B
元のテーブルの列の最小値と最大値に基づいて、関連する日付の範囲を選択しますNOT EXISTS
条件を使用して、各月末日を元のテーブルの関連レコードに結合しますSQL:
SELECT t.A, d.dt B, t.C
FROM
all_dates d
INNER JOIN (
SELECT MIN(B) minb, MAX(B) maxb FROM mytable
) trange
ON d.dt >= trange.minb AND d.dt <= trange.maxb
INNER JOIN mytable t
ON t.B <= d.dt
AND NOT EXISTS (
SELECT 1
FROM mytable t1
WHERE t1.B <= d.dt AND t1.B > t.B
)
サンプルデータを使用したdb-fiddleのこのデモは、次のようになります。
| A | B | C |
| ----------------------- | ----------- | --- |
| 10062-35551-49007-45097 | 2014-08-31 | 233 |
| 10062-35551-49007-45097 | 2014-09-30 | 233 |
| 10062-35551-49007-45097 | 2014-10-31 | 14 |
| 10062-35551-49007-45097 | 2014-11-30 | 14 |
| 10062-35551-49007-45097 | 2014-12-31 | 22 |
PS:使用しているRDBMSを指定しなかったので、MySQLを選択しました。all_tables
実際のユースケースに応じて参照テーブルを作成するコードを調整する必要がある場合があります(ただし、最終的なクエリはおそらく変更されないままです)。
ボーナス:これは、列にいくつかの異なる値が存在するユースケースを適切に処理するクエリですA
:
SELECT t.A, d.dt B, t.C
FROM
all_dates d
INNER JOIN (
SELECT A, MIN(B) minb, MAX(B) maxb
FROM mytable
GROUP BY A
) trange
ON d.dt >= trange.minb AND d.dt <= trange.maxb
INNER JOIN mytable t
ON trange.A = t.A
AND t.B <= d.dt
AND NOT EXISTS (
SELECT 1
FROM mytable t1
WHERE
t1.A = t.A
AND t1.B <= d.dt
AND t1.B > t.B
)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加