Microsoft Access 掲示板

IIF複数が上手く記述できない

6 コメント
views
4 フォロー

クエリに記述するIIFが上手く出来ません。多分()の位置、数と思うのですが色々しても駄目で困っています。
下記の条件である日付を生成したいのです。
★選択1のIDが9の時[A]=0 And [B]>0の日付、[A]>0 And [B]=0の日付、それ以外の選択1のIDが9の時の日付
★選択2のID=1の時の日付、選択2のID=5の日付、選択2が1、5以外の日付
これを下記で記述しましたが駄目なのです。間違いを指摘して頂けますでしょうか。宜しくお願いします。

IIf([選択1のID]=9,IIf([A]=0 And [B]>0,DateSerial([年],[月]-[減算値]+1,[実日]),IIf([A]>0 And [B]=0,DateSerial([年],[月]-[減算値]-1,[実日]),DateSerial([年],[月]-[減算値],[実日])),IIf([X]>[Y],DateSerial([年],[月]+1,[実日]),IIf([選択2のID]=1,DateSerial([年],[月]+1,[実日]),IIf([選択2のID]=5,DateSerial([年],[月]+1,[実日]),DateSerial([年],[月],[実日])))))))

TX
作成: 2023/11/15 (水) 13:08:09
通報 ...
1
NoName 2023/11/15 (水) 13:15:58 修正 7fdfc@46fae

ネストが深くなり過ぎですね。

可読性やメンテナンス性の面でかなり難ありのコードになっています。
階層毎に、意図する処理が行われているかテストしながら記述しましょう。

2
TX 2023/11/15 (水) 13:41:45 ddfe5@f146b

アドバイスありがとうございました。選択1のIDが9の時、[A]=0の真、偽+選択2のID以降の条件式を記述した時は生成できてたのです。選択1のIDが9の時に更に分岐(A]=0 And [B]>0、[A]>0 And [B]=0、それ以外)を付け加えようと思い質問のコードにすると生成できないのです。

3

IIf([選択1のID]=9,IIf([A]=0 And [B]>0,DateSerial([年],[月]-[減算値]+1,[実日]),IIf([A]>0 And [B]=0,DateSerial([年],[月]-[減算値]-1,[実日]),DateSerial([年],[月]-[減算値],[実日]))),IIf([X]>[Y],DateSerial([年],[月]+1,[実日]),IIf([選択2のID]=1,DateSerial([年],[月]+1,[実日]),IIf([選択2のID]=5,DateSerial([年],[月]+1,[実日]),DateSerial([年],[月],[実日])))))

こちらでどうでしょうか。構文エラーは出ないと思います。

4
TX 2023/11/15 (水) 14:17:55 ddfe5@f146b

アドバイスありがとうございました!そのコードで上手くいきました!途中の ) が不足で最後の )が多かったのですね。分岐が多く混乱してました。IIFの )はコツがあるのでしょうか? Switch関数の方がすっきりするのですが、この関数はIIFの様に偽の場合はないのですよね? 初心者で見よう見まねでしているもので。

5
hiroton 2023/11/15 (水) 17:06:40 e2c8b@f966d

最終的にすべてDateSerial(y, m, d)の計算をしているので、DateSerialを主に置くとすっきりすると思います

必要な要素をまとめて式にすると、次のように表現できそうです

DateSerial([年],[月]-[減算補正]+[月補正],[実日])

「減算補正」はマイナス計算しかないので式自体マイナスにしていますが、「月補正」はプラスマイナスあるのでプラスで作成しておきます

それぞれの補正の計算は

減算補正:IIf([選択1のID]=9,[減算値],0)

月補正:IIf([選択1のID]=9, Switch([A]=0 And [B]>0, 1, [A]>0 And [B]=0, -1, True, 0), IIf([X]>[Y] Or [選択2のID]=1 Or [選択2のID]=5, 1, 0))

のような形で作れます
これを上の式に当てはめてもいいですし、そのまま別フィールドにしてもいいでしょう


「減算補正」は簡単ですが、「月補正」は複雑ですね。求め方はこれに限りません
例えば、最終結果(1,-1,0)のグループを作る形で

//Switch([1になる条件], 1, [-1になる条件], -1, True, 0)の形にする

月補正:Switch([選択1のID]=9 And [A]=0 And [B]>0 Or [選択1のID]<>9 And ([X]>[Y] Or [選択2のID]=1 Or [選択2のID]=5), 1, [選択1のID]=9 And [A]>0 And [B]=0, -1, True, 0)

のようにしてもいいと思います
関数のネストが減るメリットはあるものの、やりたいことを直感的に表現できているか?とはちょっと離れているかな?という印象です

Switch関数は条件が真(True)になったときの値を返す関数なので、条件にTrueを指定すれば、そこで必ず値を返すことになります。「それ以前の条件で真が無ければこの値を返す」という、IIf関数における「偽のとき」の値を設定できます


条件式では様々な比較演算子を使うことができます

//↓の部分について
IIf([X]>[Y],DateSerial([年],[月]+1,[実日]),IIf([選択2のID]=1,DateSerial([年],[月]+1,[実日]),IIf([選択2のID]=5,DateSerial([年],[月]+1,[実日]),DateSerial([年],[月],[実日]))))

IIf(
  [X]>[Y]
 ,DateSerial([年],[月]+1,[実日])      // ←同じ結果を求めている
 ,IIf(
    [選択2のID]=1
   ,DateSerial([年],[月]+1,[実日])    // ←同じ結果を求めている
   ,IIf(
      [選択2のID]=5
     ,DateSerial([年],[月]+1,[実日])  // ←同じ結果を求めている
     ,DateSerial([年],[月],[実日])
    )
  )
)

このようないずれかに当てはまれば真というのはOrで表現できます

IIf([X]>[Y] Or [選択2のID]=1 Or [選択2のID]=5,DateSerial([年],[月]+1,[実日]),DateSerial([年],[月],[実日]))

Or比較はAnd比較と同じくらい使うので覚えましょう


蛇足
こう複雑な計算が必要になると、なんかこう、元のテーブル構造が怪しそうですね

6
TX 2023/11/16 (木) 08:29:22 ddfe5@f146b

hiroton様 回答ありがとうございました。なるほどです! 一旦条件分岐での補正フィールドを作りそれを参照させると大分すっきりしますね。IIFとSwitchを組み合わせることもできるのですね。論理的なアイデアは素晴らしいです。
同じ結果になるものは一つにまとめるといいですね。短時間でこんなすごいアイデアがでてくるのは、本当にすごいです。
ありがとうございました。