Active RecordでのNAND条件、NOR条件の書き方
こんにちは!ラブグラフの開発チームでインターンシップをしているけいすけと申します。
先日、Active RecordでNAND条件、NOR条件を書く機会があったのでまとめておきます。
NAND条件
NANDとはNOT ANDの略で、ANDの否定をとったものです。日本語では否定論理積といいます。
Aという条件とBという条件があるとき、
A AND Bは、AとBがどちらもtrue
のときにtrue
、それ以外の場合はfalse
になりますが、
A NAND Bは、AとBがどちらもtrue
のときにfalse
、それ以外の場合はtrue
になります。
真理値表
真理値表は次のようになります。
A | B | A AND B | A NAND B |
---|---|---|---|
false |
false |
false |
true |
false |
true |
false |
true |
true |
false |
false |
true |
true |
true |
true |
false |
ベン図
左の円に囲まれた部分をA、右の円に囲まれた部分をBとすると、
下の図の赤い部分がA NAND Bを表します。AとBが逆でも同じです。
Active Recordでの書き方
Model.where.not(A, B)
例
マッチングアプリのようなサービスを扱っていて、その中から特定の条件を満たすユーザーを取得するクエリを書く例を考えてみます。
このサービスのユーザーの名前(name
)、職業(occupation
)、趣味(hobby
)を持つ次のようなusers
テーブルがあるとします。
users
テーブル
name | occupation | hobby |
---|---|---|
一郎 | engineer | workout |
二郎 | engineer | cooking |
三郎 | designer | workout |
四郎 | designer | cooking |
このテーブルから
「職業がエンジニア」かつ「趣味が筋トレ」のユーザー以外
を取得するクエリはNAND条件の書き方を使って次のように書けます。
User.where.not(occupation: "engineer", hobby: "workout")
このクエリで取得できるのは次の3人です。
name | occupation | hobby |
---|---|---|
二郎 | engineer | cooking |
三郎 | designer | workout |
四郎 | designer | cooking |
一郎は「職業がエンジニア」かつ「趣味が筋トレ」のユーザーなので、このクエリの取得結果には含まれません。
NOR条件
NORとはNOT ORの略で、ORの否定をとったものです。日本語では否定論理和といいます。
Aという条件とBという条件があるとき、
A OR Bは、AとBのどちらかがtrue
のときにtrue
、それ以外の場合はfalse
になりますが、
A NOR Bは、AとBのどちらかがtrue
のときにfalse
、それ以外の場合はtrue
になります。
真理値表
真理値表は次のようになります。
A | B | A OR B | A NOR B |
---|---|---|---|
false |
false |
false |
true |
false |
true |
true |
false |
true |
false |
true |
false |
true |
true |
true |
false |
ベン図
左の円に囲まれた部分をA、右の円に囲まれた部分をBとすると、
下の図の赤い部分がA NOR Bを表します。AとBが逆でも同じです。
Active Recordでの書き方
Model.where.not("A OR B")
または
Model.where.not(A).where.not(B)
.where.not(A).where.not(B)
は、「Aでない」かつ「Bでない」を表します。
例
NANDの場合と同じ例で考えます。
users
テーブル
name | occupation | hobby |
---|---|---|
一郎 | engineer | workout |
二郎 | engineer | cooking |
三郎 | designer | workout |
四郎 | designer | cooking |
このテーブルから
「職業がエンジニア」または「趣味が筋トレ」のユーザー以外
を取得するクエリはNOR条件の書き方を使って次のように書けます。
User.where.not("occupation = :occupation OR hobby = :hobby", occupation: "engineer", hobby: "workout")
または
User.where.not(occupation: "engineer").where.not(hobby: "workout")
このクエリで取得できるのは次の1人です。
name | occupation | hobby |
---|---|---|
四郎 | designer | cooking |
一郎、二郎、三郎は「職業がエンジニア」または「趣味が筋トレ」のユーザーなので、このクエリの取得結果には含まれません。
以上、Active RecordでのNAND条件とNOR条件の書き方でした!
読んでいただきありがとうございました!
Discussion