トップページに戻る    次のSQLパズルへ    前のSQLパズルへ

10-164 場合の数を求めて、場合分け

SQLパズル

範囲テーブル
No  方位開始  方位終了
--  --------  --------
 1         5        25
 2       325         5
 3        45       375

度数法で、
開始角度(指定開始)と、
終了角度(指定終了)を指定して、
範囲テーブルの、方位開始から方位終了までの範囲を、
完全に含むか出力する

出力結果
No  方位開始  方位終了   指定開始  指定終了   完全に含むかフラグ
--  --------  --------  --------  --------  -----------------
 1         5        25         0        45         1
 1         5        25       315        45         1
 1         5        25       315       345         0
 2       325         5         0        45         0
 2       325         5       315        45         1
 2       325         5       315       345         0
 3        45       375         0        45         0
 3        45       375       315        45         0
 3        45       375       315       345         0

こちらを参考にさせていただきました


SQL

with 範囲テーブル as(
select 1 as No,5 as 方位開始,25 as 方位終了 from dual
union select 2,325,  5 from dual
union select 3, 45,375 from dual),
指定テーブル as(
select trunc(dbms_random.random) as 指定開始,trunc(dbms_random.random) as 指定終了
from all_objects
where RowNum <= 200)
select a.方位開始,a.方位終了,b.指定開始,b.指定終了,
     --          5         355             100       150
case when b.指定開始 <= b.指定終了 and a.方位開始 <= a.方位終了 --場合1
     then case when b.指定開始 <= a.方位開始
                and a.方位終了 <= b.指定終了 then 1 else 0 end
    --         5         355             325        15
    when b.指定開始 <= b.指定終了 and a.方位開始 > a.方位終了 --場合2
    then 0
    --       325          15               5        10
    when b.指定開始 > b.指定終了 and a.方位開始 <= a.方位終了 --場合3
    then case when (a.方位開始 between b.指定開始 and 360
                 or a.方位開始 between 0 and b.指定終了)
               and (a.方位終了 between b.指定開始 and 360
                 or a.方位終了 between 0 and b.指定終了) then 1 else 0 end
    --       325          15             335        10
    when b.指定開始 > b.指定終了 and a.方位開始 > a.方位終了 --場合4
    then case when b.指定開始 <= a.方位開始
               and a.方位終了 <= b.指定終了 then 1 else 0 end
    end as "完全に含むかフラグ変形前",
case when b.指定開始 > b.指定終了 and a.方位開始 <= a.方位終了
      and (a.方位開始 between b.指定開始 and 360 or
           a.方位開始 between 0 and b.指定終了)
      and (a.方位終了 between b.指定開始 and 360 or
           a.方位終了 between 0 and b.指定終了)
       or (b.指定開始  > b.指定終了 and a.方位開始  > a.方位終了 or
           b.指定開始 <= b.指定終了 and a.方位開始 <= a.方位終了)
       and b.指定開始 <= a.方位開始
       and a.方位終了 <= b.指定終了 then 1 else 0 end as "完全に含むかフラグ変形後",
case when mod(a.方位開始 - b.指定開始 + 360, 360)
  <= mod(b.指定終了-b.指定開始+360,360) - mod(a.方位終了-a.方位開始+360,360)
     then 1 else 0 end as "ベクトルで考える"
from (select abs(mod(方位開始,360)) as 方位開始,
             abs(mod(方位終了,360)) as 方位終了
        from 範囲テーブル) a,
     (select abs(mod(指定開始,360)) as 指定開始,
             abs(mod(指定終了,360)) as 指定終了
        from 指定テーブル) b
order by b.指定開始,b.指定終了,a.方位開始;


解説

360の剰余を求め、大小関係で場合分けしてます。

大小関係の組み合わせは、
和の法則と、積の法則より、
(1+1)*(1+1)=2*2=4 で4通り
となります。

そして、case式を使って、4通りの場合分けをしてます。

場合分けで求めた論理式を、
ブール代数を使って変形してもいいでしょう。

■■■■■■■■■■■■■■■■■■■■■■■■■■■■

各場合の不等式の上に、
コメントで具体的な角度を書いておくのは、
ドラゴン桜の10巻に出てきた
具体的なイメージから思考を始めて推理していく、
東京ドーム発想法を使ってます。

■■■■■■■■■■■■■■■■■■■■■■■■■■■■
別の方法で、
角度の移動量はこんな感じで分かるので

SQL> select mod(-1,360),
  2         mod(-1+360,360)
  3    from dual;

MOD(-1,360)■MOD(-1+360,360)
-----------■---------------
         -1■            359

SQL> select mod(200-150  +360,360),
  2         mod(150-200  +360,360)
  3   from dual;

MOD(200-150+360,360)■MOD(150-200+360,360)
--------------------■--------------------
                  50■                 310

後は、
出発地点の差
と角度の移動量の差
で不等式を立式する。
数学のベクトルで考える方法もあります。

ベクトルの資料

場合分けの資料
場合分けの資料
場合分けの資料(英語)

場合の数の資料

和の法則、積の法則の資料
和の法則、積の法則の資料
和の法則、積の法則の資料
オルタナティブ・マス・クラブ 和の法則の資料
オルタナティブ・マス・クラブ 積の法則の資料

10-132 大小比較で場合分け