QA@IT
«回答へ戻る

多重代入便利くないですか!?

887
 ```ruby
 tag1 = Tag.where(tag: "printing")
 tag2 = Tag.where(tag: "performance")
-[tag1, tag2].each_with_index.inject(Bug.scoped) {|bug_scope, tag_scope_with_index|
-  bug_scope.joins("INNER JOIN (#{tag_scope_with_index[0].to_sql}) AS tags#{tag_scope_with_index[1]} ON tags#{tag_scope_with_index[1]}.bug_id = bugs.id")
+[tag1, tag2].each_with_index.inject(Bug.scoped) {|bug_scope, (tag_scope, i)|
+  bug_scope.joins("INNER JOIN (#{tag_scope.to_sql}) AS tags#{i} ON tags#{i}.bug_id = bugs.id")
 }
 ```
 

SQLアンチパターンの例を用いて回答してみます。
moroさんの回答とそんなに変わらないですが。

habtmではなく、has_many :through関連を前提として話を進めます。
to_sqlを使って、joinsの中でSELECT文を生成するという方法で記述した事があります。
JOINしてから絞りこむのではなく、関連テーブルを先にSELECTして導出したテーブルに番号を振って、JOINしてます。

tag1 = Tag.where(tag: "printing")
tag2 = Tag.where(tag: "performance")
[tag1, tag2].each_with_index.inject(Bug.scoped) {|bug_scope, (tag_scope, i)|
  bug_scope.joins("INNER JOIN (#{tag_scope.to_sql}) AS tags#{i} ON tags#{i}.bug_id = bugs.id")
}
SELECT `bugs`.* FROM `bugs` INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "printing") AS tags0 ON tags0.bug_id = bugs.id INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "performance") AS tags1 ON tags1.bug_id = bugs.id

injectはmoroさんの回答を見てカッコ良かったので、パクりましたw
条件が動的に増減しないなら、joinsに直接書いちゃえば、もうちょっと見通し良くなると思います。

これで、同様の結果が返るはずです。
個人的にはWHERE INの中でサブクエリを使うより、こちらの方がクエリのイメージが分かりやすいのですが、どちらの方が効率良いのかなーと思ってます。

SQLアンチパターンの例を用いて回答してみます。
moroさんの回答とそんなに変わらないですが。

habtmではなく、has_many :through関連を前提として話を進めます。
to_sqlを使って、joinsの中でSELECT文を生成するという方法で記述した事があります。
JOINしてから絞りこむのではなく、関連テーブルを先にSELECTして導出したテーブルに番号を振って、JOINしてます。

```ruby
tag1 = Tag.where(tag: "printing")
tag2 = Tag.where(tag: "performance")
[tag1, tag2].each_with_index.inject(Bug.scoped) {|bug_scope, (tag_scope, i)|
  bug_scope.joins("INNER JOIN (#{tag_scope.to_sql}) AS tags#{i} ON tags#{i}.bug_id = bugs.id")
}
```

```sql
SELECT `bugs`.* FROM `bugs` INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "printing") AS tags0 ON tags0.bug_id = bugs.id INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "performance") AS tags1 ON tags1.bug_id = bugs.id
```

injectはmoroさんの回答を見てカッコ良かったので、パクりましたw
条件が動的に増減しないなら、joinsに直接書いちゃえば、もうちょっと見通し良くなると思います。

これで、同様の結果が返るはずです。
個人的にはWHERE INの中でサブクエリを使うより、こちらの方がクエリのイメージが分かりやすいのですが、どちらの方が効率良いのかなーと思ってます。

修正時の削除漏れを削除。

200
 [tag1, tag2].each_with_index.inject(Bug.scoped) {|bug_scope, tag_scope_with_index|
   bug_scope.joins("INNER JOIN (#{tag_scope_with_index[0].to_sql}) AS tags#{tag_scope_with_index[1]} ON tags#{tag_scope_with_index[1]}.bug_id = bugs.id")
 }
-
-Bug.joins("INNER JOIN (tag1.to_sql) AS 
 ```
 
 ```sql

SQLアンチパターンの例を用いて回答してみます。
moroさんの回答とそんなに変わらないですが。

habtmではなく、has_many :through関連を前提として話を進めます。
to_sqlを使って、joinsの中でSELECT文を生成するという方法で記述した事があります。
JOINしてから絞りこむのではなく、関連テーブルを先にSELECTして導出したテーブルに番号を振って、JOINしてます。

tag1 = Tag.where(tag: "printing")
tag2 = Tag.where(tag: "performance")
[tag1, tag2].each_with_index.inject(Bug.scoped) {|bug_scope, tag_scope_with_index|
  bug_scope.joins("INNER JOIN (#{tag_scope_with_index[0].to_sql}) AS tags#{tag_scope_with_index[1]} ON tags#{tag_scope_with_index[1]}.bug_id = bugs.id")
}
SELECT `bugs`.* FROM `bugs` INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "printing") AS tags0 ON tags0.bug_id = bugs.id INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "performance") AS tags1 ON tags1.bug_id = bugs.id

injectはmoroさんの回答を見てカッコ良かったので、パクりましたw
条件が動的に増減しないなら、joinsに直接書いちゃえば、もうちょっと見通し良くなると思います。

これで、同様の結果が返るはずです。
個人的にはWHERE INの中でサブクエリを使うより、こちらの方がクエリのイメージが分かりやすいのですが、どちらの方が効率良いのかなーと思ってます。

SQLアンチパターンの例を用いて回答してみます。
moroさんの回答とそんなに変わらないですが。

habtmではなく、has_many :through関連を前提として話を進めます。
to_sqlを使って、joinsの中でSELECT文を生成するという方法で記述した事があります。
JOINしてから絞りこむのではなく、関連テーブルを先にSELECTして導出したテーブルに番号を振って、JOINしてます。

```ruby
tag1 = Tag.where(tag: "printing")
tag2 = Tag.where(tag: "performance")
[tag1, tag2].each_with_index.inject(Bug.scoped) {|bug_scope, tag_scope_with_index|
  bug_scope.joins("INNER JOIN (#{tag_scope_with_index[0].to_sql}) AS tags#{tag_scope_with_index[1]} ON tags#{tag_scope_with_index[1]}.bug_id = bugs.id")
}
```

```sql
SELECT `bugs`.* FROM `bugs` INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "printing") AS tags0 ON tags0.bug_id = bugs.id INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "performance") AS tags1 ON tags1.bug_id = bugs.id
```

injectはmoroさんの回答を見てカッコ良かったので、パクりましたw
条件が動的に増減しないなら、joinsに直接書いちゃえば、もうちょっと見通し良くなると思います。

これで、同様の結果が返るはずです。
個人的にはWHERE INの中でサブクエリを使うより、こちらの方がクエリのイメージが分かりやすいのですが、どちらの方が効率良いのかなーと思ってます。

回答を投稿

SQLアンチパターンの例を用いて回答してみます。
moroさんの回答とそんなに変わらないですが。

habtmではなく、has_many :through関連を前提として話を進めます。
to_sqlを使って、joinsの中でSELECT文を生成するという方法で記述した事があります。
JOINしてから絞りこむのではなく、関連テーブルを先にSELECTして導出したテーブルに番号を振って、JOINしてます。

tag1 = Tag.where(tag: "printing")
tag2 = Tag.where(tag: "performance")
[tag1, tag2].each_with_index.inject(Bug.scoped) {|bug_scope, tag_scope_with_index|
  bug_scope.joins("INNER JOIN (#{tag_scope_with_index[0].to_sql}) AS tags#{tag_scope_with_index[1]} ON tags#{tag_scope_with_index[1]}.bug_id = bugs.id")
}

Bug.joins("INNER JOIN (tag1.to_sql) AS 
SELECT `bugs`.* FROM `bugs` INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "printing") AS tags0 ON tags0.bug_id = bugs.id INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "performance") AS tags1 ON tags1.bug_id = bugs.id

injectはmoroさんの回答を見てカッコ良かったので、パクりましたw
条件が動的に増減しないなら、joinsに直接書いちゃえば、もうちょっと見通し良くなると思います。

これで、同様の結果が返るはずです。
個人的にはWHERE INの中でサブクエリを使うより、こちらの方がクエリのイメージが分かりやすいのですが、どちらの方が効率良いのかなーと思ってます。

SQLアンチパターンの例を用いて回答してみます。
moroさんの回答とそんなに変わらないですが。

habtmではなく、has_many :through関連を前提として話を進めます。
to_sqlを使って、joinsの中でSELECT文を生成するという方法で記述した事があります。
JOINしてから絞りこむのではなく、関連テーブルを先にSELECTして導出したテーブルに番号を振って、JOINしてます。

```ruby
tag1 = Tag.where(tag: "printing")
tag2 = Tag.where(tag: "performance")
[tag1, tag2].each_with_index.inject(Bug.scoped) {|bug_scope, tag_scope_with_index|
  bug_scope.joins("INNER JOIN (#{tag_scope_with_index[0].to_sql}) AS tags#{tag_scope_with_index[1]} ON tags#{tag_scope_with_index[1]}.bug_id = bugs.id")
}

Bug.joins("INNER JOIN (tag1.to_sql) AS 
```

```sql
SELECT `bugs`.* FROM `bugs` INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "printing") AS tags0 ON tags0.bug_id = bugs.id INNER JOIN (SELECT `tags`.* FROM `tags` WHERE `tags`.`tag` = "performance") AS tags1 ON tags1.bug_id = bugs.id
```

injectはmoroさんの回答を見てカッコ良かったので、パクりましたw
条件が動的に増減しないなら、joinsに直接書いちゃえば、もうちょっと見通し良くなると思います。

これで、同様の結果が返るはずです。
個人的にはWHERE INの中でサブクエリを使うより、こちらの方がクエリのイメージが分かりやすいのですが、どちらの方が効率良いのかなーと思ってます。