SQLを書こう (実践編 - 合計残高試算表)

28
SQL をををを 実実実 - 実実実実実実実 実実実実実実実

Transcript of SQLを書こう (実践編 - 合計残高試算表)

SQL を書こう実践編 - 合計残高試算表

なかじまゆうじ

はじめに

このスライドは、 SQL の構文を覚えた新人に、実際に SQL 文を書くときの考え方を説明するために作成したものです。標準 SQL を想定していますが、一部、 SQL Server に依存している部分があります。

「合計残高試算表」ってなに?

会計の帳票の 1 つです。仕訳帳を勘定科目ごとに貸借金額を合計した

ものです。「借方残高」「借方合計」「勘定科目名」

「貸方合計」「貸方残高」の 5 列で構成されます。

「合計残高試算表」ってなに?

「借方合計」には、勘定科目ごとの借方の合計金額が入ります。

「貸方合計」には、勘定科目ごとの貸方の合計金額が入ります。

「合計残高試算表」ってなに?

「借方残高」と「貸方残高」には、勘定科目ごとの残高が入ります。残高が借方にある場合には「借方残高」、貸方にある場合には「貸方残高」に入ります。

「残高」ってなんだっけ?

借方金額と貸方金額の大きい方から小さい方の金額を引いた残りです。

借方の方が大きければ借方に残高がある状態、貸方の方が大きければ貸方に残高がある状態です。

ということは

勘定科目ごとの借方合計金額と貸方合計金額があれば(これが合計試算表です)、残高の部分は簡単に作れます。

つまり、こんな感じ。

select ( 借方合計 - 貸方合計 ) as 借方残高 , 勘定科目名 , ( 貸方合計 - 借方合計 ) as 貸方残高from 合計試算表

小さい方の貸借に、マイナス金額が出ちゃうじゃん。。。

小さい方は出ないようにしよう。select case when 借方合計 > 貸方合計 then ( 借方合計 - 貸方合計 ) else null end as 借方残高 , 勘定科目名 , case when 借方合計 < 貸方合計 then ( 貸方合計 - 借方合計 ) else null end as 貸方残高from 合計試算表

残高はできた。あとは合計試算表をどう作るか。

「仕訳帳」ってどんな構造?

本来は「借方勘定科目と金額」「貸方勘定科目と金額」が、それぞれ複数行存在するものです。

今回は、「勘定科目名」「貸借」「金額」の3 列のテーブルと考えます。

「勘定科目ごとの合計金額」なら

select 勘定科目名 , sum( 金額 ) as 合計金額from 仕訳帳group by 勘定科目名

「勘定科目ごとの借方合計金額」なら

select 勘定科目名 , sum( 金額 ) as 借方合計from 仕訳帳where 貸借 = ' 借方 'group by 勘定科目名

「勘定科目ごとの貸方合計金額」なら

select 勘定科目名 , sum( 金額 ) as 貸方合計from 仕訳帳where 貸借 = ' 貸方 'group by 勘定科目名

両方繋ぐと?select 借方 . 借方合計 , 借方 . 勘定科目名 , 貸方 . 貸方合計from ( select 勘定科目名 , sum( 金額 ) as 借方合計 from 仕訳帳 where 貸借 = ' 借方 ' group by 勘定科目名 ) as 借方inner join ( select 勘定科目名 , sum( 金額 ) as 貸方合計 from 仕訳帳 where 貸借 = ' 貸方 ' group by 勘定科目名 ) as 貸方 on 貸方 . 勘定科目名 = 借方 . 勘定科目名

片方にしかない勘定科目がなくなる!

left outer だと?select 借方 . 借方合計 , 借方 . 勘定科目名 , 貸方 . 貸方合計from ( select 勘定科目名 , sum( 金額 ) as 借方合計 from 仕訳帳 where 貸借 = ' 借方 ' group by 勘定科目名 ) as 借方left outer join ( select 勘定科目名 , sum( 金額 ) as 貸方合計 from 仕訳帳 where 貸借 = ' 貸方 ' group by 勘定科目名 ) as 貸方 on 貸方 . 勘定科目名 = 借方 . 勘定科目名

貸方にしかない科目がなくなる!

full outer だと?select 借方 . 借方合計 , 借方 . 勘定科目名 , 貸方 . 貸方合計from ( select 勘定科目名 , sum( 金額 ) as 借方合計 from 仕訳帳 where 貸借 = ' 借方 ' group by 勘定科目名 ) as 借方full outer join ( select 勘定科目名 , sum( 金額 ) as 貸方合計 from 仕訳帳 where 貸借 = ' 貸方 ' group by 勘定科目名 ) as 貸方 on 貸方 . 勘定科目名 = 借方 . 勘定科目名

貸方にしかない勘定科目の勘定科目名が出ない!

最終的に、こんな感じ。select 借方 . 借方合計 , coalesce( 借方 . 勘定科目名 , 貸方 . 勘定科目名 ) as 勘定科目名 , 貸方 . 貸方合計from ( select 勘定科目名 , sum( 金額 ) as 借方合計 from 仕訳帳 where 貸借 = ' 借方 ' group by 勘定科目名 ) as 借方full outer join ( select 勘定科目名 , sum( 金額 ) as 貸方合計 from 仕訳帳 where 貸借 = ' 貸方 ' group by 勘定科目名 ) as 貸方 on 貸方 . 勘定科目名 = 借方 . 勘定科目名

仕訳帳が from に 2 回も登場して、遅そう。

余談:遅い SQL の特徴

遅い(実行時間が長い) SQL になる条件はいろいろありますが、「 from 句に登場するテーブル(実表)の数が多い」場合も遅くなりがちです。

「実表」というのが曲者で、 view の場合はその中に含まれる実表の数になります。

ということで、別解。select sum(case when 貸借 = ' 借方 ' then 金額 else 0 end) as 借方合計 , 勘定科目名 , sum(case when 貸借 = ' 貸方 ' then 金額 else 0 end) as 貸方合計from 仕訳帳group by 勘定科目名

最終的に合計残高試算表はselect case when 借方合計 > 貸方合計 then ( 借方合計 - 貸方合計 ) else null end as 借方残高 , 借方合計 , 勘定科目名 , 貸方合計 , case when 借方合計 < 貸方合計 then ( 貸方合計 - 借方合計 ) else null end as 貸方残高from ( select sum(case when 貸借 = ' 借方 ' then 金額 else 0 end) as 借方合計 , 勘定科目名 , sum(case when 貸借 = ' 貸方 ' then 金額 else 0 end) as 貸方合計 from 仕訳帳 group by 勘定科目名 ) as 合計試算表

まとめ

join のときは、行がなくならないように気をつける。

事前に絞り込んでおかなくても、必要な情報を 1 つの行に並べられれば、 select 句でなんとかなる。

欲しいテーブルがなければ、作る。from 句に登場する実表の数に気をつける。

おしまい