説明:SQLの操作はpsycopg2を使って、Python上での操作を行いました。
1.2021年1月12日
勉強したSQL構文:
OVER(PARTITION BY column1 ORDER BY column2)
①データ挿入
%%sql
CREATE TABLE T0104(
ID INT,
NAME VARCHAR(10),
NUM INT)
INSERT INTO T0104 VALUES(1,'A',1);
INSERT INTO T0104 VALUES(2,'A',2);
INSERT INTO T0104 VALUES(3,'A',6);
INSERT INTO T0104 VALUES(4,'A',4);
INSERT INTO T0104 VALUES(5,'A',3);
INSERT INTO T0104 VALUES(6,'B',2);
INSERT INTO T0104 VALUES(7,'B',8);
INSERT INTO T0104 VALUES(8,'B',2);

%%sql
select A.id,A.name,A.num from(
select T.ID,T.NAME,T.NUM,
sum(NUM) OVER(PARTITION BY NAME ORDER BY ID)*1.0 a,
sum(NUM) OVER(PARTITION BY NAME ORDER BY ID) *1.0 b,
sum(NUM) OVER(PARTITION BY NAME)*1.0 c from T0104 as T
) A
where A.a/A.c > 0.6;

2.2021年1月13日
勉強したSQL構文:
1.column1をもとに分割し、column2をもとにそれぞれ順番そろえて、順位を新しい列につけて行く
row_number() over(partion column1 order by column2)
2.coalesce関数
coalesce(A,B,C…):()の中に一つの非NULLの値が出力される
参考記事:CASE式で条件分岐をSQL文に任せる
3.条件分岐構文:検索case式
case
when column1 = '' then 結果1
when column1 = '' then 結果2
else ●●
END
①まず条件分岐で正負の検索結果をつけていき、コードごとに順番並ぶ
%%sql
SELECT *,
case when 金額相違値 >= 0 then '正'
when 金額相違値 < 0 then '負'
else '' end as 増長方向,
row_number() over(partition by コード order by 日付) rn from T0113

%%sql
select b.rn from u b
where b.コード = a.コード
and b.rn<a.rn
and b.増長方向 != a.増長方向
order by b.rn desc limit 1
③上記条件を満足されない行に関しては、null値になるので、coalesce関数でnull値を0に変更し、aのrn行と引き算を行い、連続増長日数という新しい一列にする。
select 日付,コード,金額,金額相違値,増長方向,
a.rn - coalesce((select b.rn from u b
where b.コード = a.コード
and b.rn<a.rn
and b.増長方向 != a.増長方向
order by b.rn desc limit 1),0) "連続増長日数" from u a
④完成版と結果は以下の通り
%%sql
with u as
(SELECT *,
case when 金額相違値 >= 0 then '正'
when 金額相違値 < 0 then '負'
else '' end as 増長方向,
row_number() over(partition by コード order by 日付) rn
from T0113)
select 日付,コード,金額,金額相違値,増長方向,
a.rn - coalesce((select b.rn from u b
where b.コード = a.コード
and b.rn<a.rn
and b.増長方向 != a.増長方向
order by b.rn desc limit 1),0) "連続増長日数" from u a

3.2021年1月16日
select 商品,日付,sum(単価*個数)/sum(個数) as 平均単価
from (select *,
dense_rank() OVER(PARTITION BY 商品 ORDER BY 日付) from T0116)as a
where dense_rank = 1
group by 商品,日付;

4.2021年1月17日
勉強したSQL構文:
CONCATを使って、数字型と文字型の結合異なるデータ型を結合したい
参考記事:SQL 文字列結合メモ
①まずover()関数を使ってコードごとにグループ分けを行い、順位をつける
select *,row_number() over(PARTITION by L order by x) as m from T0117

select *,x-row_number() over(PARTITION by L order by x) as m from T0117

concat((min(x),'-',max(x)))
④まとめる
select l,concat(min(x),'-',max(x)) as y from
(select *,x-row_number() over(PARTITION by L order by x) as m from T0117
) as a
group by l,m;

5.2021年1月21日
勉強したSQL構文:
DATEから年月のみを取得
①後ほど条件判定を行えるため、DATEから年月のみを取得
select *,to_char(mon,'YYYY-MM') as MONTH from T0121;

with u as
(select *,to_char(mon,'YYYY-MM') as MONTH from T0121)
select id,name,month,state,amount/(select count(*) from u as b
where a.month=b.month
and b.name = a.name) as number
from u as a;

6.2021年1月25日
postgresql:to_char([元列名], ‘YYYY-MM-DD HH24:MI’)
mysqlなら:date_format([元列名], ‘%Y-%m-%d %H:%i’)
②join結合テーブル
③with as使いすぎるとメモリが食われやすいので、要注意
①データの型をお題通りに揃える
select *,to_char(TransTime,'YYYY-MM-DD HH24:MI') as TransTimed from T0125;

with u as
(select *,to_char(TransTime,'YYYY-MM-DD HH24:MI') as TransTimed from T0125)
select *,row_number() over(PARTITION BY opcode order by transtimed) as rn from u;

with uu as
(with u as
(select *,to_char(TransTime,'YYYY-MM-DD HH24:MI') as TransTimed from T0125)
select *,row_number() over(PARTITION BY opcode order by transtimed) as rn from u)
select a.transtype as transtype_1,b.transtype as transtype_2,a.oprseq,a.opcode,a.rn,
a.transtimed as starttime,b.transtimed as endtime from uu as a
left join uu as b
on b.opcode=a.opcode
and b.rn = a.rn+1;

with result as
(with uu as
(with u as
(select *,to_char(TransTime,'YYYY-MM-DD HH24:MI') as TransTimed from T0125)
select *,row_number() over(PARTITION BY opcode order by transtimed) as rn from u)
select a.transtype as transtype_1,b.transtype as transtype_2,a.oprseq,a.opcode,a.rn,
a.transtimed as starttime,b.transtimed as endtime from uu as a
left join uu as b
on b.opcode=a.opcode
and b.rn = a.rn+1
where a.rn %2!=0)
select concat(result.transtype_1,'-',result.transtype_2) as transtype,result.oprseq,result.opcode,result.starttime,result.endtime
from result;

7.2021年1月26日
①テーブルを作成し、データを挿入する
1 | create table T0126A |
ポイント1:serial
- テーブルの列に一意の識別子を設定する簡便な表記法
- integer列(整数列)が作成され、その列のデフォルト値が連番整数を振り当てる
- PostgreSQL7.3及び以降のバージョンでは、UNIQUEまたはPRIMARY KEYにしたい場合、他のすべてのデータ型と同様に指定する必要がある
- mysqlならAUTO_INCREMENT,OracleならSEQUENCE(PostgreSQLも)で連番を採番できる
- 書き方
CREATE TABLE tablename(
columnname SERIAL);
参考記事:シリアルデータ型
②spmcごとに累計購入量を計算する
1 | select *, (select sum(購入量) from T0126B as B |
1 | with T as( |
④列名をお題通りに変更する
1 | with T as |